package com.jld.vod.utils.http

import com.google.gson.GsonBuilder
import com.jld.vod.base.MyApplication
import com.jld.vod.config.Config
import com.jld.vod.model.bean.*
import com.jld.vod.interfaces.remote.Apis
import com.jld.vod.utils.http.FileRequestBody
import com.jld.vod.utils.http.RetrofitCallback
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.util.concurrent.TimeUnit


/**
 * Create by Panda on 2019/1/15
 */
object RetrofitUtils {

    lateinit var apis: Apis

    fun init(): Apis {

        val builder = OkHttpClient.Builder()
//        val loggingInterceptor =
//            HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
//                override fun log(message: String) {
//                    try {
//                        val text: String = URLDecoder.decode(message, "utf-8")
//                        Log.e("OKHttp-----", text)
//                    } catch (e: UnsupportedEncodingException) {
//                        e.printStackTrace()
//                        Log.e("OKHttp-----", message)
//                    }
//                }
//            })
        val loggingInterceptor = HttpLoggingInterceptor()//不重写,部分手机平板需要打开日志
        if (MyApplication.isDebug()) {
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        } else {
            loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
        }

        builder//.addInterceptor(loggingInterceptor)
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)


        val retrofit = Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
                .baseUrl(
                        if (MyApplication.isDebug()) {//测试版
                            Config.ApiBaseUrlDebug
                        } else {//发行版
                            Config.ApiBaseUrl
                        })
                .client(builder.build())
                .build()
        apis = retrofit.create(Apis::class.java)
        return apis
    }

    /**
     * 获取车辆信息
     */
    fun carInfo(observer: (bean: BaseBean<List<CarInfoBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.carInfo().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取车辆运行信息
     */
    fun carRunInfo(observer: (bean: BaseBean<CarRunInfoBean>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.carRunInfo().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取所有语言信息
     */
    fun findLanguageAll(observer: (userBean: BaseBean<List<LanguageBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findLanguageAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取全部模块信息
     */
    fun findModularAll(userid:Long, observer: (userBean: BaseBean<List<ModelAllBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findModularAll(userid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 根据模块编号获取所有一级类别
     */
//    fun findCategoryFatherAllByMid(mid:String,lid:Long, observer: (userBean: BaseBean<List<CategoryFatherAllBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findCategoryFatherAllByMid(mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }

    /**
     * 根据类别编号获取所有二级类别
     */
//    fun findCategorySonAllByCid(cid:Long,lid:Long, observer: (userBean: BaseBean<List<CategorySonAllBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findCategorySonAllByCid(cid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }

    /**
     * 根据模块编号查询电影信息
     */
//    fun findMovieByMid(mid:Long, lid:Long, observer: (userBean: BaseBean<List<MovieByMidBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findMovieByMid(mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }
    /**
     * 根据类别编号获取电影信息
     */
//    fun findMovieByCid(cid: Long, mid:Long, lid:Long, observer: (userBean: BaseBean<List<MovieByMidBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findMovieByCid(cid,mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }

    /**
     * 文件电影上传（POST请求）
     */
    fun movieUpload(file: File,mid: Long,resId:Long,callback: RetrofitCallback<*>, observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {

        val body1: RequestBody = RequestBody.create("application/otcet-stream".toMediaTypeOrNull(), file)

        //通过该行代码将RequestBody转换成特定的FileRequestBody
        val body = FileRequestBody(body1, callback)

        val part: MultipartBody.Part = // RetrofitFileUtils.uploadFile("file",file);
            MultipartBody.Part.createFormData("file", file.getName(), body)

        val disposable = apis.movieUpload(part,mid,resId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 根据模块编号查询音乐信息
     */
//    fun findMusicByMid(mid:Long, lid:Long, observer: (userBean: BaseBean<List<MusicByMidBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findMusicByMid(mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }

    /**
     * 根据类别编号获取音乐信息
     */
//    fun findMusicByCid(cid: Long, mid:Long, lid:Long, observer: (userBean: BaseBean<List<MusicByMidBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findMusicByCid(cid,mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }

    /**
     * 获取所有游戏信息
     */
//    fun findGameAll(mid:Long, lid:Long,terminal :String ,observer: (userBean: BaseBean<List<GameBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findGameAll(mid,lid,terminal).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }

    /**
     * 根据模块编号查询网络链接信息
     */
//    fun findNetWorkAll(mid:Long, lid:Long, observer: (userBean: BaseBean<List<BrowserBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findNetWorkAll(mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }


    /**
     * 检测APP是否有更新（与云服务器交互）
     */
    fun detectAppUpdates(userId:Long,versionNum:Long, observer: (userBean: AppUpdateInfo) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.detectAppUpdates(userId,versionNum).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 下载云apk到本地服务器（与云服务器交互）
     */
    fun previewAPK(apkFile:String, observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.previewAPK(apkFile).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 检测车辆是否绑定云平台
     */
    fun eqCar(observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.eqCar().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取用户未绑定车辆
     */
    fun findCarByUnbound(userId:Long, observer: (userBean: BaseBean<List<FindCarByUnboundBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findCarByUnbound(userId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 车辆绑定云平台
     */
    fun binding(ciId:String, observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.binding(ciId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取关于信息资源
     */
//    fun findAboutAll(mid:Long,lid:Long, observer: (userBean: BaseBean<List<FindAboutAllBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
//        val disposable = apis.findAboutAll(mid,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe(observer, error)
//        return disposable
//    }
    /**
     * 文件音乐上传（POST请求）
     */
    fun musicUpload(file: File,mid: Long,resId:Long,callback: RetrofitCallback<*>, observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {

        val body1: RequestBody = RequestBody.create("application/otcet-stream".toMediaTypeOrNull(), file)

        //通过该行代码将RequestBody转换成特定的FileRequestBody
        val body = FileRequestBody(body1, callback)

        val part: MultipartBody.Part = // RetrofitFileUtils.uploadFile("file",file);
            MultipartBody.Part.createFormData("file", file.getName(), body)

        val disposable = apis.musicUpload(part,mid,resId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取音乐未上传列表
     */
    fun findResByNotUploadedmusic(observer: (userBean: BaseBean<List<MusicResByNotUploaded>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findResByNotUploadedmusic().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取电影未上传列表
     */
    fun findResByNotUploadedmovie(observer: (userBean: BaseBean<List<MovieResByNotUploaded>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findResByNotUploadedmovie().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取该车辆所有站点信息
     */
    fun findCarSiteAll(ciId: Long, lid: Long, observer: (userBean: BaseBean<List<CarSiteAllBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findCarSiteAll(ciId,lid).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取游戏未上传列表
     */
    fun findResByNotUploadedgame(observer: (userBean: BaseBean<List<GameResByNotUploaded>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findResByNotUploadedgame().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 文件游戏上传（POST请求）
     */
    fun gameUpload(file: File,mid: Long,resId:Long,callback: RetrofitCallback<*>, observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {

        val body1: RequestBody = RequestBody.create("application/otcet-stream".toMediaTypeOrNull(), file)

        //通过该行代码将RequestBody转换成特定的FileRequestBody
        val body = FileRequestBody(body1, callback)

        val part: MultipartBody.Part = // RetrofitFileUtils.uploadFile("file",file);
            MultipartBody.Part.createFormData("file", file.getName(), body)

        val disposable = apis.gameUpload(part,mid,resId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取未安装游戏列表
     */
    fun findGameByNoInstall(terminal :String,observer: (userBean: BaseBean<List<FindGameByNoInstallBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findGameByNoInstall(terminal).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 更新游戏安装状态
     */
    fun updateGameInstallState(resId :String,install :String,terminal :String,observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.updateGameInstallState(resId,install,terminal).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取所有静态资源
     */
    fun findAllModularImg(userId :String,observer: (userBean: BaseBean<findAllModularImgBean>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findAllModularImg(userId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取所有静态资源(new)
     */
    fun findAllModularRotateImg(userId :String,index: Int,observer: (userBean: BaseBean<List<AllModularRotateImgBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findAllModularRotateImg(userId,index).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 获取所有静态资源(new)
     */
    fun findHomePageImg(observer: (userBean: BaseBean<HomePageImgBean>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findHomePageImg().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 返回需要卸载的游戏
     */
    fun getNuInstallGame(terminal :String,observer: (userBean: BaseBean<List<NuInstallGameBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.getNuInstallGame(terminal).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer, error)
        return disposable
    }

    /**
     * 删除安装目录
     */
    fun delInstallPath(tiId:String,observer: (userBean: BaseBean<List<NuInstallGameBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.delInstallPath(tiId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer, error)
        return disposable
    }
    /**
     * 获取固定位置广告
     */
    fun findPositionAdvert(observer: (userBean: BaseBean<List<PositionAdvertBean>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findPositionAdvert().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }
    /**
     * 获取GEO广告
     */
    fun findGEOAdvert(observer: (userBean: BaseBean<List<String>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findGEOAdvert().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }
    /**
     * 获取电影广告
     */
    fun findMovieAdvert(observer: (userBean: BaseBean<List<String>>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.findMovieAdvert().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer, error)
        return disposable
    }

    /**
     * 绑定用户
     */
    fun updateUser(userId:String,observer: (userBean: BaseBean<String>) -> Unit, error: (t: Throwable) -> Unit): Disposable {
        val disposable = apis.updateUser(userId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer, error)
        return disposable
    }
}

