package com.zhaohaoting.framework.abs.datasource;

import android.arch.lifecycle.LifecycleOwner;

import com.zhaohaoting.framework.R;
import com.zhaohaoting.framework.abs.entity.ItemModel;
import com.zhaohaoting.framework.abs.entity.ResultEntity;
import com.zhaohaoting.framework.application.ZhtApplication;
import com.zhaohaoting.framework.mvchelper.mvc.IAsyncDataSource;
import com.zhaohaoting.framework.mvchelper.mvc.IDataAdapter;
import com.zhaohaoting.framework.mvchelper.mvc.IDataCacheLoader;
import com.zhaohaoting.framework.mvchelper.mvc.RequestHandle;
import com.zhaohaoting.framework.mvchelper.mvc.ResponseSender;
import com.zhaohaoting.framework.mvchelper.okhttp.exception.RequestException;
import com.zhaohaoting.framework.mvchelper.utils.NetworkUtils;
import com.zhaohaoting.framework.requset.rxjava_retrofit.RxBodyResultSubscriber;
import com.zhaohaoting.framework.utils.DataSupportCache;
import com.zhaohaoting.framework.utils.Logger;

import org.litepal.crud.DataSupport;
import org.reactivestreams.Subscription;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;

/**
 * author：Created by ZHT on 2017/11/13 14:17
 * email：526309416@qq.com
 * desc：列表 RESULT_DATA为BaseListEntity<DATA>或List<DATA></>
 */
@SuppressWarnings("unchecked")
public abstract class RxBodySource<DATA, RESULT_DATA> implements IAsyncDataSource<RESULT_DATA>, IDataCacheLoader<RESULT_DATA> {

    protected int initPage = 1;//初始页码
    protected int page;//当前页码
    protected int nextPage = 1;//下一页页码

    public static int rows = 10;//每页大小
    protected int currentTotal = 0;
    protected boolean isPaging = true;//此列表是否分页
    protected Class<DATA> tCls;
    protected Class<RESULT_DATA> resultCls;
    protected String orderColumn = "";//"createTime desc"
    protected String[] whereColumn = {""};//查询条件
    protected boolean canUseCache = false;//此列表是否做缓存
    private boolean isRunning = true;
    private DoneActionRegister register;

    public RxBodySource() {
        page = initPage;
        tCls = ((Class<DATA>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
        Type type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        if (type instanceof ParameterizedType) {
            resultCls = (Class<RESULT_DATA>) ((ParameterizedType) type).getRawType();
        } else {
            resultCls = (Class<RESULT_DATA>) type;
        }
        register = new DoneActionRegister();
//        resultCls = (Class<RESULT_DATA>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
    }


    @Override
    public final RequestHandle refresh(final ResponseSender<RESULT_DATA> sender) throws Exception {
        nextPage = initPage;
        return load(sender, loadDataSource(nextPage));
    }

    @Override
    public final RequestHandle loadMore(ResponseSender<RESULT_DATA> sender) throws Exception {
        nextPage = page + 1;
        return load(sender, loadDataSource(nextPage));
    }

    protected Flowable<ResponseBody> loadDataSource(int pageNumber) {
        HashMap<String, Object> params = new HashMap<>();
        if (isPaging) {
            params.put("page", pageNumber);
            params.put("rows", rows);
        }
        return loadListFromNetWork(params);
    }

    protected abstract Flowable<ResponseBody> loadListFromNetWork(HashMap<String, Object> params);


    @Override
    public boolean hasMore() {
        return currentTotal == rows;
    }

    private RequestHandle load(final ResponseSender<RESULT_DATA> sender, final Flowable<ResponseBody> observable) {
        final RxBodyResultSubscriber subscriber = new RxBodyResultSubscriber<RESULT_DATA, ResultEntity<RESULT_DATA>>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                register.addSubscription(subscription);
                subscription.request(Long.MAX_VALUE);//设置请求数
            }

            @Override
            protected void onSuccess(RESULT_DATA dataSource) {
//                if (dataSource instanceof BaseListEntity) {
//                    total = ((BaseListEntity) dataSource).getTotal();
//                    pageNumber++;
//                }
                if (dataSource != null) {
                    if (dataSource instanceof List) {
                        List source = (List) dataSource;
                        currentTotal = source.size();
                        if (currentTotal != 0) {
                            page = nextPage;
                        }
                    }
                }
                requestSuccess(sender, dataSource);
            }

            @Override
            protected void onFailure(int code, String tipMsg) {
                sender.sendError(new RequestException(tipMsg).setCode(code));
                isRunning = false;
            }
        };
        observable.doOnSubscribe(new Consumer<Subscription>() {
            @Override
            public void accept(Subscription subscription) throws Exception {
                if (!NetworkUtils.hasNetwork(ZhtApplication.getContext())) {//没有网络
                    subscription.cancel();
                    sender.sendError(new RequestException(ZhtApplication.getContext().getResources().getString(R.string.bad_network)));
                }
            }
        }).subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
        return new RequestHandle() {
            @Override
            public void onDestroy(LifecycleOwner owner) {
                cancel();
            }

            @Override
            public void cancel() {
                for (Subscription subscription : register.subscriptions) {
                    subscription.cancel();
                }
            }

            @Override
            public boolean isRunning() {
                return isRunning;
            }
        };
    }

    protected void requestSuccess(ResponseSender<RESULT_DATA> sender, RESULT_DATA dataSource) {
        isRunning = false;
        sender.sendData(dataSource);
    }

    @Override
    public RESULT_DATA loadCache(IDataAdapter<RESULT_DATA> adapter) {
//        if (isEmpty && canUseCache) {
        if (adapter.isEmpty() && canUseCache) {
            if (resultCls.isAssignableFrom(List.class)) {
                List<DATA> dataList = DataSupport.where(whereColumn).order(orderColumn).limit(rows).find(tCls);
                return (RESULT_DATA) dataList;
            }
            throw new RuntimeException("RESULT_DATA Type error");
        }
        return null;
    }

    @Override
    public void setCache(final RESULT_DATA result_data) {
        if (!canUseCache) return;
        if (ItemModel.class.isAssignableFrom(tCls)) {
            DataSupportCache.saveAllAsync((List<ItemModel>) result_data, (Class<? extends ItemModel>) tCls, success -> Logger.e(tCls.getName(), success ? "缓存成功" : "缓存失败"), whereColumn);
        }
    }

    public void setPage(RESULT_DATA dataSource) {
    }

    public static class DoneActionRegister {
        private List<Subscription> subscriptions = new ArrayList<>();

        public void addSubscription(final Subscription subscription) {
            subscriptions.add(subscription);
        }
    }

}
