package com.byoutline.kickmaterial.fragments;
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.view.*;
import android.widget.ImageView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.byoutline.cachedfield.CachedFieldWithArg;
import com.byoutline.cachedfield.FieldState;
import com.byoutline.cachedfield.FieldStateListener;
import com.byoutline.ibuscachedfield.util.RetrofitHelper;
import com.byoutline.kickmaterial.KickMaterialApp;
import com.byoutline.kickmaterial.R;
import com.byoutline.kickmaterial.activities.ProjectDetailsActivity;
import com.byoutline.kickmaterial.adapters.ProjectClickListener;
import com.byoutline.kickmaterial.adapters.ProjectsAdapter;
import com.byoutline.kickmaterial.adapters.SharedViews;
import com.byoutline.kickmaterial.events.CategoriesFetchedEvent;
import com.byoutline.kickmaterial.events.DiscoverProjectsFetchedErrorEvent;
import com.byoutline.kickmaterial.events.DiscoverProjectsFetchedEvent;
import com.byoutline.kickmaterial.managers.LoginManager;
import com.byoutline.kickmaterial.model.*;
import com.byoutline.kickmaterial.utils.LUtils;
import com.byoutline.kickmaterial.views.EndlessRecyclerView;
import com.byoutline.ottoeventcallback.PostFromAnyThreadBus;
import com.byoutline.secretsauce.utils.ViewUtils;
import com.software.shell.fab.ActionButton;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.parceler.Parcels;
import timber.log.Timber;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.List;
import static com.byoutline.kickmaterial.activities.CategoriesListActivity.ARG_CATEGORY;
import static com.byoutline.kickmaterial.activities.CategoriesListActivity.launch;
/**
* @author Pawel Karczewski <pawel.karczewski at byoutline.com> on 2015-01-03
*/
public class ProjectsListFragment extends KickMaterialFragment implements ProjectClickListener, FieldStateListener, EndlessRecyclerView.EndlessScrollListener {
public static final String PREFS_SHOW_HEADER = "PREFS_SHOW_HEADER";
private static final int BG_COLOR_MAX = 255;
private static final int BG_COLOR_MIN = 232;
private static final String INSTANCE_STATE_SUMMARY_SCROLLED = "INSTANCE_STATE_SUMMARY_SCROLLED";
public float summaryScrolled;
@BindView(R.id.project_recycler_view)
EndlessRecyclerView projectListRv;
@BindView(R.id.swipe_refresh_projects_srl)
SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.bubbles_iv)
ImageView bubblesIv;
@BindView(R.id.show_categories_fab)
ActionButton showCategoriesFab;
@BindView(R.id.main_parent_rl)
View mainParent;
@Inject
Bus bus;
@Inject
CachedFieldWithArg<DiscoverResponse, DiscoverQuery> discoverField;
@Inject
LoginManager loginManager;
@Inject
SharedPreferences sharedPreferences;
private View rootView;
private ProjectsAdapter adapter;
private float actionbarScrollPoint;
private float maxScroll;
private int page = 1;
private int lastAvailablePage = Integer.MAX_VALUE;
private Category category;
/**
* Endless scroll variables *
*/
private GridLayoutManager layoutManager;
public static ProjectsListFragment newInstance(@Nullable Category category) {
ProjectsListFragment instance = new ProjectsListFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_CATEGORY, Parcels.wrap(category));
instance.setArguments(args);
return instance;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_projects, container, false);
KickMaterialApp.component.inject(this);
ButterKnife.bind(this, rootView);
hostActivity.enableActionBarAutoHide(projectListRv);
maxScroll = 2 * getResources().getDimensionPixelSize(R.dimen.project_header_padding_top) + ViewUtils.dpToPx(48, getActivity());
actionbarScrollPoint = ViewUtils.dpToPx(24, getActivity());
getArgs();
setHasOptionsMenu(true);
return rootView;
}
private void getArgs() {
Bundle args = getArguments();
if (args != null && args.containsKey(ARG_CATEGORY)) {
category = Parcels.unwrap(args.getParcelable(ARG_CATEGORY));
} else {
Timber.e("Category not passed");
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpAdapters();
setUpListeners();
configureSwipeRefresh();
}
public void configureSwipeRefresh() {
int altColor = category == null ? R.color.green_dark : category.colorResId;
swipeRefreshLayout.setColorSchemeResources(altColor, R.color.green_primary);
swipeRefreshLayout.setOnRefreshListener(() -> {
// Throw away all loaded categories and start over.
int pageToRefresh = 1;
discoverField.refresh(DiscoverQuery.getDiscoverQuery(category, pageToRefresh));
});
}
@Override
protected void setUpListeners() {
super.setUpListeners();
projectListRv.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > actionbarScrollPoint) {
hostActivity.showActionbar(false, true);
if (!showCategoriesFab.isHidden()) {
showCategoriesFab.hide();
}
}
if (dy < actionbarScrollPoint * (-1)) {
hostActivity.showActionbar(true, true);
if (showCategoriesFab.isHidden()) {
showCategoriesFab.show();
}
}
summaryScrolled += dy;
bubblesIv.setTranslationY(-0.5f * summaryScrolled);
float alpha = summaryScrolled / maxScroll;
alpha = Math.min(1.0f, alpha);
hostActivity.setToolbarAlpha(alpha);
//change background color on scroll
int color = (int) Math.max(BG_COLOR_MIN, BG_COLOR_MAX - summaryScrolled * 0.05);
mainParent.setBackgroundColor(Color.argb(255, color, color, color));
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putFloat(INSTANCE_STATE_SUMMARY_SCROLLED, summaryScrolled);
super.onSaveInstanceState(outState);
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
summaryScrolled = savedInstanceState.getFloat(INSTANCE_STATE_SUMMARY_SCROLLED);
}
super.onViewStateRestored(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
restoreDefaultScreenLook();
bus.register(this);
discoverField.addStateListener(this);
loadCurrentPage();
if (category != null) {
showCategoriesFab.setButtonColor(ContextCompat.getColor(getContext(), category.colorResId));
}
}
@Override
public void onPause() {
discoverField.removeStateListener(this);
bus.unregister(this);
super.onPause();
}
private void loadCurrentPage() {
final DiscoverQuery query = DiscoverQuery.getDiscoverQuery(category, page);
discoverField.postValue(query);
// loginManager.logIn(EmailAndPass.create("g774092@trbvm.com", "g774092@trbvm.com"));
}
private void setUpAdapters() {
/** NEW ADAPTER **/
layoutManager = new GridLayoutManager(getActivity(), 2);
final boolean showHeader = sharedPreferences.getBoolean(PREFS_SHOW_HEADER, true);
// TODO: decide when to hide it.
sharedPreferences.edit().putBoolean(PREFS_SHOW_HEADER, false).apply();
final ProjectsAdapter.ItemViewTypeProvider itemViewTypeProvider = new ProjectsAdapter.ItemViewTypeProvider(showHeader);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (itemViewTypeProvider.getViewType(position) == ProjectsAdapter.NORMAL_ITEM) {
return 1;
}
return 2;
}
});
projectListRv.setEndlessScrollListener(this);
projectListRv.setLayoutManager(layoutManager);
adapter = new ProjectsAdapter(getActivity(), this, showHeader, itemViewTypeProvider);
projectListRv.setAdapter(adapter);
}
private void restoreDefaultScreenLook() {
hostActivity.showActionbar(true, false);
LUtils.setStatusBarColor(getActivity(), ContextCompat.getColor(getContext(), R.color.status_bar_color));
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@OnClick(R.id.show_categories_fab)
public void showCategories() {
// projectListRv.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.projects_list_hide_anim));
launch(getActivity(), category, showCategoriesFab);
}
@Override
public String getFragmentActionbarName() {
if (category != null) {
return getString(category.nameResId);
} else {
return "Projects";
}
}
@Override
public boolean showBackButtonInActionbar() {
return false;
}
@Override
public void projectClicked(int position, SharedViews views) {
Project project = adapter.getItem(position);
views.add(showCategoriesFab);
ProjectDetailsActivity.launch(getActivity(), project, views.asArray());
}
private boolean isDiscoverFetchErrorCausedByLastPage(DiscoverProjectsFetchedErrorEvent event) {
Exception exception = event.getResponse();
if (exception instanceof RetrofitHelper.ApiException) {
RetrofitHelper.ApiException ex = (RetrofitHelper.ApiException) exception;
if (ex.errorResponse != null && ex.errorResponse.code() == 404) {
return true;
}
}
return false;
}
@Subscribe
public void onCategoriesFetched(CategoriesFetchedEvent event) {
ViewUtils.showDebugToast(event.getResponse().toString());
}
@Subscribe
public void onDiscoverProjectsFail(DiscoverProjectsFetchedErrorEvent event) {
if (isDiscoverFetchErrorCausedByLastPage(event)) {
Integer failedPage = event.getArgValue().getPageFromQuery();
if (failedPage != null) {
page = failedPage - 1;
lastAvailablePage = page;
}
}
}
@Subscribe
public void onDiscoverProjects(DiscoverProjectsFetchedEvent event) {
// ignore search result.
if (event.getArgValue().discoverType != DiscoverType.SEARCH) {
if (event.getResponse().projects != null && event.getResponse().projects.size() > 0) {
lastAvailablePage = Integer.MAX_VALUE;
}
List<Project> projects = event.getResponse().projects;
if (page == 1) {
adapter.setItems(projects);
} else {
adapter.addItems(projects);
}
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
SearchView searchView = SearchListFragment.getSearchView(getActivity(), menu);
searchView.setIconified(true);
searchView.setOnSearchClickListener(v -> hostActivity.showFragment(new SearchListFragment(), true));
}
@Override
public void fieldStateChanged(FieldState newState) {
PostFromAnyThreadBus.runInMainThread(() -> {
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(newState == FieldState.CURRENTLY_LOADING);
}
});
}
@Override
public int getLastVisibleItemPosition() {
return layoutManager.findLastVisibleItemPosition();
}
@Override
public void loadMoreData() {
page++;
loadCurrentPage();
}
private boolean hasMore() {
return page < lastAvailablePage;
}
@Override
public synchronized boolean hasMoreDataAndNotLoading() {
return (!(discoverField.getState() == FieldState.CURRENTLY_LOADING) && hasMore());
}
}