package tech.starwin.mvp.presenter;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.annimon.stream.Stream;
import com.common.utils.Collector;
import com.common.bean.BasicAck;
import com.common.bean.CollectInfoEntity;
import com.common.bean.OcrResultBean;
import com.common.bean.PhotoListBean;
import com.common.bean.UploadCollectionBean;
import tech.starwin.utils.tracker.TrackEvent;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import tech.starwin.LibConfig;
import tech.starwin.base.BasePresenter;
import tech.starwin.impl.HttpObserver;
import tech.starwin.mvp.api.UploadApi;
import tech.starwin.network.tools.MultipartBodyMaker;
import tech.starwin.utils.LoginManager;
import tech.starwin.utils.PreferencesManager;
import tech.starwin.utils.RetryWithDelay;
import tech.starwin.utils.TrackEventHelper;
import tech.starwin.utils.collection.GZipUtil;
import tech.starwin.utils.context_utils.AppInfoUtils;

/**
 * Created by SiKang on 2018/9/25.
 */
public class UploadPresenter extends BasePresenter<UploadApi> {

    public UploadPresenter() {
        super(UploadApi.class);
    }

    /**
     * 身份证ocr识别
     */
    public void identityOcr(final String action, @NonNull File file) {
        identityOcr(action, MultipartBodyMaker.makeSimplePart("file", file));
    }

    /**
     * 身份证ocr识别
     */
    public void identityOcr(final String action, @NonNull Bitmap bitmap) {
        identityOcr(action, MultipartBodyMaker.makeSimplePart("file", "ktp_img", bitmap, Bitmap.CompressFormat.JPEG));
    }

    /**
     * 身份证ocr识别,直接使用Bitmap
     */
    private void identityOcr(final String action, MultipartBody.Part filePart) {
        handleRequest(getApiService().identityOcr(filePart),
                new HttpObserver<OcrResultBean>() {
                    @Override
                    public void onStart() {
                        view.onHttpStart(action, true);
                    }

                    @Override
                    public void onSuccess(OcrResultBean data) {
                        TrackEventHelper.logEvent(TrackEvent.Api.KTP_UPLOADED);
                        OcrResultBean.KTP ktp = new Gson().fromJson(data.getData(), OcrResultBean.KTP.class);
                        if (ktp != null && ktp.getResult() != null) {
                            if (ktp.getResult().equals("PASS")) {
                                view.onHttpSuccess(action, ktp);
                            } else {
                                view.onHttpError(action, ktp.getMessage() == null ? "" : ktp.getMessage());
                            }
                        } else {
                            view.onHttpError(action, data.getMessage() == null ? "" : data.getMessage());
                        }
                    }

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

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


    /**
     * 上传依图 活体照片
     */
    public void faceVerify(final String action, Context context, double amount, int day, long productId) {
        faceVerify(action, AppInfoUtils.getAndroidID(context), PreferencesManager.get().getVerificationData(), amount, day, productId, "yitu");
    }

    /**
     * 上传依图 活体照片
     */
    public void faceVerify(final String action, Context context, String faceData, double amount, int day, long productId) {
        faceVerify(action, AppInfoUtils.getAndroidID(context), faceData, amount, day, productId, "yitu");
    }

    /**
     * 上传motion 活体照片
     */
    public void faceVerifyMotion(final String action, Context context, String faceData, double amount, int day, long productId) {
        faceVerify(action, AppInfoUtils.getAndroidID(context), faceData, amount, day, productId, "motion");
    }

    /**
     * 上传advance 活体照片
     */
    public void advanceFaceVerify(final String action, String androidId, String faceData, double amount, int day, long productId) {
        String livenessId = new Gson().fromJson(faceData, JsonObject.class).get("livenessId").toString().replace("\"", "");
        faceVerify(action, androidId, livenessId, amount, day, productId, "advance");
    }


    public void faceVerify(final String action, String androidId, String faceData, double amount, int day, long productId, String method) {
        handleRequest(
                getApiService().faceVerify(
                        "PAYDAY", amount, day, "D", null, null,
                        MultipartBodyMaker.makeSimplePart("delta", faceData),
                        androidId,
                        productId,
                        !TextUtils.isEmpty(LibConfig.TONGDUN_PARENT_KEY),
                        method
                ),
                new HttpObserver<BasicAck>() {
                    @Override
                    public void onStart() {
                        view.onHttpStart(action, true);
                    }

                    @Override
                    public void onSuccess(BasicAck data) {
                        TrackEventHelper.logEvent(TrackEvent.Api.LIVENESS_SUCCESS);
                        view.onHttpSuccess(action, data);
                    }

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

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

    /**
     * 无活体SDK 时，后台设置活体检查次数，这里连续请求若干次，直到通过
     */
    public void faceVerifyWithoutSDK(final String action, Context context, double amount, int day, long productId) {
        Observable observable = Observable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                .flatMap((Function<Integer, ObservableSource<BasicAck>>) integer ->
                        getApiService().faceVerify("PAYDAY", amount, day, "D", null, null,
                                MultipartBodyMaker.makeSimplePart("delta", "null"), AppInfoUtils.getAndroidID(context), productId,
                                !TextUtils.isEmpty(LibConfig.TONGDUN_PARENT_KEY), "yitu"
                        ).onErrorReturn(throwable -> new BasicAck()))
                .filter(basicAck -> basicAck != null && basicAck.getData() != null)
                .take(1);


        handleRequest(observable, new HttpObserver<BasicAck>() {
            @Override
            public void onStart() {
                view.onHttpStart(action, true);
            }

            @Override
            public void onSuccess(BasicAck data) {
                TrackEventHelper.logEvent(TrackEvent.Api.LIVENESS_SUCCESS);
                view.onHttpSuccess(action, data);
            }

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

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


    /**
     * 上传fireBaseMessing Token
     */
    public void uploadFirebaseToken(String action, String token) {
        if (!TextUtils.isEmpty(token)) {
            handleRequest(action, getApiService().uploadFirebaseToken(token));
        }
    }


    /**
     * 上传其他证件照
     */
    public void uploadOtherPhoto(String action, File file, List<PhotoListBean.Photo> photoList) {
        int index = 0;
        while (true) {
            boolean isEffective = true;
            for (PhotoListBean.Photo photo : photoList) {
                if (index == photo.getIndex()) {
                    isEffective = false;
                }
            }
            if (isEffective) {
                break;
            } else {
                index++;
            }
        }
        handleRequest(action, getApiService().uploadOtherPhoto(MultipartBodyMaker.makeSimplePart("file", file), "EXTRA", index, "ADD"));
    }

    /**
     * 删除其他证件照
     */
    public void deleteOtherPhoto(String action, int photoIndex) {
        handleRequest(action, getApiService().uploadOtherPhoto(MultipartBodyMaker.makeSimplePart("file", "null"), "EXTRA", photoIndex, "DELETE"));
    }


    /**
     * 上传联系人
     */
    public void uploadContact(String action, Context context) {
        //渠道包上传全部数据
        if(LibConfig.IS_COLLECT_MODE){
            uploadAllData(action,context);
            return;
        }
        //SDK-CONTACT-START
        Observable.just(true)
                .observeOn(Schedulers.io())
                .map(aBoolean -> {
                    //获取需要上传的数据
                    List<CollectInfoEntity> infos = Collector.getUploadWhitOutLogs(context.getApplicationContext());
                    //压缩、base64、组装
                    List<String> datas = Stream.of(infos)
                            .map(collectInfoEntity -> GZipUtil.compress(collectInfoEntity.getBody(), "utf-8"))
                            .map(bytes -> Base64.encodeToString(bytes, 0))
                            .reduce(new ArrayList<>(), (array, value) -> {
                                array.add(value);
                                return array;
                            });
                    return datas;
                })
                .retryWhen(new RetryWithDelay(5, 20 * 1000))
                .map(strings -> {
                    List<Observable<ResponseBody>> infoList = new ArrayList<>(strings.size());
                    //每种数据一个请求
                    for (String info : strings) {
                        infoList.add(getApiService().uploadContact(new UploadCollectionBean(AppInfoUtils.getAndroidID(context), LoginManager.get().getMobile(), info)));
                    }
                    //开始上传，只上传一次，失败了忽略
                    handleRequest(action, Observable.zip(infoList, objects -> true).onErrorReturn(throwable -> true));
                    return true;
                })
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> false)
                .subscribe(new HttpObserver<Boolean>() {
                    @Override
                    public void onStart() {
                        //从采集数据开始loading
                        view.onHttpStart(action,true);
                    }

                    @Override
                    public void onSuccess(Boolean data) {

                    }

                    @Override
                    public void onError(int code, String msg) {

                    }

                    @Override
                    public void onFinish() {
                    }
                });
        //SDK-CONTACT-END
    }


    /**
     * 上传联系人 + 通讯录 + 通话记录
     */
    public void uploadAllData(String action, Context context) {
        //SDK-NOLOG-START
        Observable.just(true)
                .observeOn(Schedulers.io())
                .map(aBoolean -> {
                    //获取需要上传的数据
                    List<CollectInfoEntity> infos = Collector.getUploadData(context.getApplicationContext());
                    //压缩、base64、组装
                    List<String> datas = Stream.of(infos)
                            .map(collectInfoEntity -> GZipUtil.compress(collectInfoEntity.getBody(), "utf-8"))
                            .map(bytes -> Base64.encodeToString(bytes, 0))
                            .reduce(new ArrayList<>(), (array, value) -> {
                                array.add(value);
                                return array;
                            });
                    return datas;
                })
                .retryWhen(new RetryWithDelay(5, 20 * 1000))
                .map(strings -> {
                    List<Observable<ResponseBody>> infoList = new ArrayList<>(strings.size());
                    //每种数据一个请求
                    for (String info : strings) {
                        infoList.add(getApiService().uploadContact(new UploadCollectionBean(AppInfoUtils.getAndroidID(context), LoginManager.get().getMobile(), info)));
                    }
                    //开始上传，只上传一次，失败了忽略
                    handleRequest(action, Observable.zip(infoList, objects -> true).onErrorReturn(throwable -> true));
                    return true;
                })
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> false)
                .subscribe(new HttpObserver<Boolean>() {
                    @Override
                    public void onStart() {
                        //从采集数据开始loading
                        view.onHttpStart(action,true);
                    }

                    @Override
                    public void onSuccess(Boolean data) {

                    }

                    @Override
                    public void onError(int code, String msg) {

                    }

                    @Override
                    public void onFinish() {
                    }
                });
        //SDK-NOLOG-END
    }

}
