
package com.ydl.ydlcommon.data.http

import com.ydl.ydlcommon.base.BaseApp
import com.ydl.ydlcommon.base.lifecycle.ILifecycleable
import com.ydl.ydlcommon.mvp.base.IView
import com.ydl.ydlcommon.mvp.lce.ILceView
import com.ydl.ydlcommon.utils.RxLifecycleUtils
import com.yidianling.common.tools.RxNetTool
import io.reactivex.Observable
import io.reactivex.ObservableTransformer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.net.ConnectException

/**
 * author : Zhangwenchao
 * e-mail : zhangwch@yidianling.com
*/
object RxUtils {

    // 在子线程中把实体参数类转换成 map
    @JvmStatic
    fun <T> mapObservable(t: T): Observable<HashMap<String, String>> {
        return Observable.just(t)
                .compose(netCheck())
                .subscribeOn(Schedulers.io())
                .map { MapUtils.bean2Map(it) }
    }

    /**
     * 若网络未连接，抛出未连接异常
     */
    @JvmStatic
    fun <T>netCheck(): ObservableTransformer<T, T> {
        return ObservableTransformer {
            if (RxNetTool.isConnected(BaseApp.getApp())) it
            else Observable.error(ConnectException())
        }
    }

    /**
     * 若状态码不为0，抛出接口异常
     */
    @JvmStatic
    fun <T> handleResult(): ObservableTransformer<Response<T>, Response<T>> {
        return ObservableTransformer {
            it.flatMap {
                if (it.code == 0) Observable.just(it)
                else Observable.error(ApiThrowable(it.msg))
            }
        }
    }

    /**
     * 根据返回数据，得到真正需要的数据
     * 若状态码不为0，抛出接口异常
     */
    @JvmStatic
    fun <T> resultData(): ObservableTransformer<BaseResponse<T>, T> {
        return ObservableTransformer {
            it.flatMap {
                if (it.code == 0) Observable.just(it.data)
                else Observable.error(Throwable(it.msg, Throwable(it.code.toString())))
            }
        }
    }

    /**
     * java跟php返回结构不一致 所以新写了一个方法
     * 根据返回数据，得到真正需要的数据
     * 若状态码不为200，抛出接口异常
     */
    @JvmStatic
    fun <T> resultJavaData(): ObservableTransformer<BaseAPIResponse<T>, T> {
        return ObservableTransformer {
            it.flatMap {
                if (it.code == "200") Observable.just(it.data)
                else {
                    Observable.error(Throwable(it.msg, Throwable(it.code)))
                }
            }
        }
    }

    //====================Rxjava 线程调度====================

    /**
     * RxJava 线程协调 / RxLifecycle绑定方法
     * 自动调用 showLoading/hideLoading 方法
     * @param view LceView 强转使用
     */
    @JvmStatic
    fun <T> applySchedulers(view: ILceView): ObservableTransformer<T, T> {
        return ObservableTransformer { observable ->
            observable.subscribeOn(Schedulers.io())
                .doOnSubscribe {
                    view.showLoading()//显示进度条
                }
                .subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally {
                    view.hideLoading()//隐藏进度条
                }.compose(RxLifecycleUtils.bindToLifecycle(view))
        }
    }

    /**
     * RxJava 线程协调 / RxLifecycle绑定方法
     *
     */
    @JvmStatic
    fun <T> applySchedulers(view: IView): ObservableTransformer<T, T> {
        return ObservableTransformer { observable ->
            observable.subscribeOn(Schedulers.io())
                .subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(RxLifecycleUtils.bindToLifecycle(view))
        }
    }

    @JvmStatic
    fun <T> applySchedulers(iLifecycleable: ILifecycleable<*> ?= null): ObservableTransformer<T, T> {
        if (iLifecycleable == null){
            return applySchedulers()
        }
        return ObservableTransformer { observable ->
            observable.subscribeOn(Schedulers.io())
                .subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(RxLifecycleUtils.bindToLifecycle(iLifecycleable))
        }
    }

    /**
     * RxJava 线程协调方法
     */
    @JvmStatic
    fun <T> applySchedulers(): ObservableTransformer<T, T> {
        return ObservableTransformer { observable ->
            observable.subscribeOn(Schedulers.io())
                .subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread())
        }
    }

}