package starter.kit.feature.rx;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.anthony.rxlibrary.R;
import com.paginate.Paginate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.ButterKnife;
import rx.Observable;
import rx.functions.Action1;
import starter.kit.feature.StarterContentFragment;
import starter.kit.feature.StarterFragConfig;
import starter.kit.model.entity.Entity;
import starter.kit.retrofit.ErrorResponse;
import starter.kit.util.ErrorHandler;
import starter.kit.util.ProgressInterface;
import starter.kit.util.RxIdentifier;
import starter.kit.util.RxPager;
import starter.kit.util.RxRequestKey;
import support.ui.adapters.BaseEasyViewHolderFactory;
import support.ui.adapters.EasyRecyclerAdapter;
import support.ui.adapters.EasyViewHolder;
import static rx.android.schedulers.AndroidSchedulers.mainThread;
import static starter.kit.util.Utilities.isAdapterEmpty;
import static starter.kit.util.Utilities.isNotNull;
public abstract class RxStarterRecyclerFragment
extends StarterContentFragment<RxResourcePresenter>
implements com.paginate.Paginate.Callbacks,
ProgressInterface,
SwipeRefreshLayout.OnRefreshListener {
SwipeRefreshLayout mSwipeRefreshLayout;
RecyclerView mRecyclerView;
private EasyRecyclerAdapter mAdapter;
private Paginate mPaginate;
private StarterFragConfig mFragConfig;
private RxRequestKey mRequestKey;
public RxRequestKey getRequestKey() {
return mRequestKey;
}
public EasyRecyclerAdapter getAdapter() {
return mAdapter;
}
public RecyclerView getRecyclerView() {
return mRecyclerView;
}
protected void buildFragConfig(StarterFragConfig fragConfig) {
if (fragConfig == null) return;
mFragConfig = fragConfig;
if (fragConfig.isWithIdentifierRequest()) {
mRequestKey = buildRxIdentifier(fragConfig);
} else {
mRequestKey = buildRxPager(fragConfig);
}
BaseEasyViewHolderFactory viewHolderFactory = fragConfig.getViewHolderFactory();
if (viewHolderFactory != null) {
mAdapter.viewHolderFactory(viewHolderFactory);
}
//noinspection unchecked
HashMap<Class, Class<? extends EasyViewHolder>> boundViewHolders = fragConfig.getBoundViewHolders();
if (!boundViewHolders.isEmpty()) {
for (Map.Entry<Class, Class<? extends EasyViewHolder>> entry : boundViewHolders.entrySet()) {
mAdapter.bind(entry.getKey(), entry.getValue());
}
}
// bind empty value
}
private RxRequestKey buildRxIdentifier(StarterFragConfig fragConfig) {
return new RxIdentifier(fragConfig.getPageSize(), new Action1<RxIdentifier>() {
@Override
public void call(RxIdentifier rxIdentifier) {
getPresenter().requestNext(rxIdentifier);
}
});
}
private RxRequestKey buildRxPager(StarterFragConfig fragConfig) {
return new RxPager(fragConfig.getStartPage(), fragConfig.getPageSize(), new Action1<RxPager>() {
@Override
public void call(RxPager pager) {
getPresenter().requestNext(pager);
}
});
}
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
mAdapter = new EasyRecyclerAdapter(getContext());
}
@Override
protected int getFragmentLayout() {
return R.layout.starter_recycler_view;
}
@Override
public View provideContentView() {
return mSwipeRefreshLayout;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSwipeRefreshLayout = ButterKnife.findById(view, R.id.swipeRefreshLayout);
mRecyclerView = ButterKnife.findById(view, R.id.support_ui_content_recycler_view);
setupRecyclerView();
setupPaginate();
setupSwipeRefreshLayout();
if (isNotNull(mFragConfig)) {
List<Object> items = mFragConfig.getItems();
if (isNotNull(items) && !items.isEmpty()) {
mAdapter.addAll(items);
}
}
}
private void setupSwipeRefreshLayout() {
if (mFragConfig != null) {
int[] colors = mFragConfig.getColorSchemeColors();
if (colors != null) {
mSwipeRefreshLayout.setColorSchemeColors(colors);
}
boolean enabled = mFragConfig.isEnabled();
mSwipeRefreshLayout.setEnabled(enabled);
if (enabled) {
mSwipeRefreshLayout.setOnRefreshListener(this);
}
}
}
private void setupPaginate() {
if (mFragConfig != null) {
if (mFragConfig.canAddLoadingListItem()) {
mPaginate = Paginate.with(mRecyclerView, this)
.setLoadingTriggerThreshold(mFragConfig.getLoadingTriggerThreshold())
.addLoadingListItem(true)
.setLoadingListItemCreator(mFragConfig.getLoadingListItemCreator())
.setLoadingListItemSpanSizeLookup(() -> mFragConfig.getSpanSizeLookup())
.build();
mPaginate.setHasMoreDataToLoad(false);
}
}
}
private void setupRecyclerView() {
mRecyclerView.setAdapter(mAdapter);
if (mFragConfig != null) {
RecyclerView.LayoutManager layoutManager = mFragConfig.getLayoutManager();
if (layoutManager != null) {
mRecyclerView.setLayoutManager(layoutManager);
} else {
mRecyclerView.setLayoutManager(newLayoutManager());
}
RecyclerView.ItemDecoration decor = mFragConfig.getDecor();
if (decor != null) {
mRecyclerView.addItemDecoration(decor);
}
RecyclerView.ItemAnimator animator = mFragConfig.getAnimator();
if (animator != null) {
mRecyclerView.setItemAnimator(animator);
}
}
}
private RecyclerView.LayoutManager newLayoutManager() {
return new LinearLayoutManager(getContext());
}
@Override
public void showProgress() {
Observable.empty().observeOn(mainThread()).doOnTerminate(() -> {
if (isAdapterEmpty(mAdapter)) {
getContentPresenter().displayLoadView();
} else if (isNotNull(mRequestKey) && mRequestKey.isFirstPage()) {
mSwipeRefreshLayout.setRefreshing(true);
} else if (isNotNull(mPaginate)) {
mPaginate.setHasMoreDataToLoad(true);
}
}).subscribe();
}
@Override
public void hideProgress() {
Observable.empty().observeOn(mainThread())
.doOnTerminate(() -> {
if (isNotNull(mSwipeRefreshLayout)) {
mSwipeRefreshLayout.setRefreshing(false);
}
})
.subscribe();
}
public void notifyDataSetChanged(ArrayList<? extends Entity> items) {
if (mRequestKey.isFirstPage()) {
mAdapter.clear();
}
mAdapter.appendAll(items);
mRequestKey.received(items);
if (isNotNull(mPaginate)) {
mPaginate.setHasMoreDataToLoad(false);
}
if (isAdapterEmpty(mAdapter)) {
getContentPresenter().displayEmptyView();
} else {
getContentPresenter().displayContentView();
}
}
public void onError(Throwable throwable) {
ErrorResponse errorResponse = ErrorHandler.handleThrowable(throwable);
if (mRequestKey.isFirstPage() && mAdapter.isEmpty()) {
mAdapter.clear();
}
if (isNotNull(mPaginate)) {
mPaginate.setHasMoreDataToLoad(false);
}
if (isAdapterEmpty(mAdapter)) {
getContentPresenter().displayErrorView();
}
}
@Override
public void onResume() {
super.onResume();
if (isNotNull(mRequestKey) && !mRequestKey.requested()) {
getPresenter().request();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
mSwipeRefreshLayout = null;
mRecyclerView = null;
}
@Override
public void onDestroy() {
super.onDestroy();
mAdapter = null;
mFragConfig = null;
mPaginate = null;
}
@Override
public void onRefresh() {
mRequestKey.reset();
getPresenter().request();
}
// Paginate delegate
@Override
public void onLoadMore() {
if (isNotNull(mPaginate) && isNotNull(mRequestKey)
&& !isAdapterEmpty(mAdapter)
&& mRequestKey.hasMoreData()
&& !isLoading()) {
mPaginate.setHasMoreDataToLoad(true);
mRequestKey.next();
}
}
@Override
public boolean isLoading() {
return isNotNull(mSwipeRefreshLayout)
&& isNotNull(mRequestKey)
&& (mSwipeRefreshLayout.isRefreshing() || mRequestKey.isLoading());
}
@Override
public boolean hasLoadedAllItems() {
return isNotNull(mRequestKey) && !mRequestKey.hasMoreData();
}
@Override
public void onEmptyViewClick(View view) {
onRefresh();
}
@Override
public void onErrorViewClick(View view) {
onRefresh();
}
}