package tech.starwin.base;


import android.annotation.SuppressLint;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import tech.starwin.impl.HttpObserver;
import tech.starwin.mvp.IView;
import tech.starwin.mvp.api.UploadApi;
import tech.starwin.network.ServiceGenerator;

/**
 * Created by SiKang on 2018/9/14.
 */
public class BasePresenter<T> {
    protected String TAG;
    protected IView view;
    protected T apiService;

    /**
     * 使用默认的HttpClient
     */
    public BasePresenter(Class<T> service) {
        TAG = getClass().getSimpleName();
        apiService = ServiceGenerator.getService(service);
    }


    @SuppressLint("CheckResult")
    public void bindIView(IView view) {
        this.view = view;
    }

    /**
     * 处理请求
     */
    protected <T> void handleRequest(Observable<T> observable, Observer<T> observer) {
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(view.<T>bindToLifecycle())
                .subscribe(observer);
    }


    protected <T> void handleRequest(final String action, Observable<T> observable) {
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(view.<T>bindToLifecycle())
                .subscribe(new HttpObserver<T>(action) {
                    @Override
                    public void onStart() {
                        view.onHttpStart(action, true);
                    }

                    @Override
                    public void onSuccess(T data) {
                        view.onHttpSuccess(action, data);
                    }

                    @Override
                    public void onError(int code, String msg) {
                        view.onHttpError(action, msg);
                    }

                    @Override
                    public void onFinish() {
                        view.onHttpFinish(action);
                    }
                });
    }

    protected <T> void handleRequest(Call<T> call, final Observer<T> observer) {
        observer.onSubscribe(null);
        call.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
                bindLifecycle(new Consumer() {
                    @Override
                    public void accept(Object o) throws Exception {
                        observer.onNext(response.body());
                    }
                });

            }

            @Override
            public void onFailure(Call<T> call, final Throwable t) {
                bindLifecycle(new Consumer() {
                    @Override
                    public void accept(Object o) throws Exception {
                        observer.onError(t);
                    }
                });
            }
        });
    }

    /**
     * 允许Null返回 不触发OnError
     */
    protected <T> Observable<T> clearError(Observable<T> observable, final T result) {
        return observable.onErrorReturn(new Function<Throwable, T>() {
            @Override
            public T apply(Throwable throwable) throws Exception {
                return result;
            }
        });
    }

    protected <T> Observable<T> clearError(Observable<T> observable, final Class<T> clz) {
        return observable.onErrorReturn(new Function<Throwable, T>() {
            @Override
            public T apply(Throwable throwable) throws Exception {
                return clz.newInstance();
            }
        });
    }

    @SuppressLint("CheckResult")
    private void bindLifecycle(Consumer consumer) {
        Observable.just(true)
                .observeOn(AndroidSchedulers.mainThread())
                .compose(view.<Boolean>bindToLifecycle())
                .subscribe(consumer);
    }


    public <T> T getService(Class<T> tClass) {
        return ServiceGenerator.getService(tClass);
    }


    public void onDestory() {
        view = null;
//        apiService = null;
    }


}
