package com.ydl.ydlcommon.base.config

import android.content.Context
import android.text.TextUtils
import com.facebook.stetho.okhttp3.StethoInterceptor
import com.ydl.ydlcommon.base.BaseApp
import com.ydl.ydlcommon.data.PlatformDataManager
import com.ydl.ydlcommon.data.http.EncryptUtils
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.utils.YDLCacheUtils
import com.ydl.ydlnet.builder.config.OkHttpConfig
import com.yidianling.common.tools.RxAppTool
import com.yidianling.common.tools.RxDeviceTool
import okhttp3.FormBody
import okhttp3.Interceptor
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okio.Buffer
import okio.BufferedSink
import java.util.*








/**
 * Created by haorui on 2019-08-30 .
 * Des: 默认Http配置参数类
 */
class HttpConfig {

    companion object {

        //====================应用默认配置====================

        private const val AUTHORIZATION_NAME = "Authorization"
        private const val SESSION_KEY = "dc59cf294f37d237c1f06240568ffe21"
        private const val YDL = "Ydl"
        private const val UID = "uid"
        private const val FFROM = "ffrom"
        private const val IS_FROM_APP = "isFromApp"
        private const val OS_BUILD = "osBuild"
        private const val TS = "ts"
        private const val VERSION = "version"
        private const val TOKEN = "accessToken"
        private val OS_TYPE = "osType"// 1.ios 2.android
        private val APP_NAME = "appName"//用于标识 是哪个应用 yidianling:用户版 xinlizixun：心理咨询 haoshi：情感壹点灵 zhuanjia：专家版

        //====================网络环境====================

        var PHP_BASE_URL = ""
        var JAVA_BASE_URL = ""
        var YDL_H5 = ""
        var H5_URL = ""
        var MH5_URL = ""
        var WEB_URL = ""
        var SERVER_COUPON_URL = ""
        var SERVER_TEMP_JAVA_URL = ""
        var SERVER_API_JAVA_URL = ""
        var ACTION_URL = ""

        fun getInstance(): HttpConfig {
            return Holder.INSTANCE
        }
    }

    fun createOkHttp(context: Context, appFrom: String, appDebug: Boolean): OkHttpClient {
        //获取证书
        val cerInputStream = context.resources.openRawResource(com.ydl.ydlcommon.R.raw.ydl_trust);
        val builder = OkHttpConfig.Builder(context);
        if (appDebug) {
            builder.setNetInterceptor(StethoInterceptor())
        }else{
            //使用预埋证书，校验服务端证书
            builder.setSslSocketFactory(cerInputStream)
        }

        return builder
            .setInterceptor(commonParams(),requestHead(appFrom))
            .setReadTimeout(15)
            .setWriteTimeout(15)
            .setConnectTimeout(15)
            .setDebug(appDebug)
            .build()
    }


    // 添加公共参数
    private fun commonParams(): Interceptor {
        return Interceptor {
            var request = it.request()
            //如果是POST请求，则再在Body中增加公共参数
            if ("POST"==request.method()){
                var body = request.body()
                if (body is FormBody) {
                    val bodyBuild = FormBody.Builder()
                    for (i in 0 until body.size()) {
                        val name = body.name(i)
                        val value = body.value(i)
                        // 去除假参数和值为空的参数
                        if (YDLConstants.HOLDER_PARAM != name && !TextUtils.isEmpty(value)) {
                            bodyBuild.addEncoded(name, value)
                        }
                    }
                    bodyBuild.addEncoded(FFROM, PlatformDataManager.getRam().getChannelName())
                        .addEncoded(IS_FROM_APP, "1")
                        .addEncoded(
                            OS_BUILD,
                            """${RxDeviceTool.getBuildBrandModel()},${RxDeviceTool.getSDKVersionName()},${RxAppTool.getAppVersionName(
                                BaseApp.getApp()
                            )}"""
                        )
                        .addEncoded(TS, (System.currentTimeMillis() / 1000).toString())
                        .addEncoded(
                            VERSION, RxAppTool.getAppVersionName(
                                BaseApp.getApp()
                            )
                        )
                    val loginBean = ModularServiceManager.getPlatformUserService()?.getUser()
                    if (loginBean != null) {
                        bodyBuild.addEncoded(UID, loginBean.userId)
                        bodyBuild.addEncoded(TOKEN, loginBean.token)
                    }

                    body = bodyBuild.build()
                }
                it.proceed(request.newBuilder().post(body!!).build())
            } else if ("GET"==request.method()){
                val url = request.url()
                val newBuilder = url.newBuilder()

//                for (i in 0 until url.querySize()) {
//                    //取出url中？后的参数
//                    val key = url.queryParameterName(i)
//                    val value = url.queryParameterValue(i)
//                    newBuilder.
//                        addQueryParameter(key, value)
//                }

                newBuilder.
                    addQueryParameter(FFROM, PlatformDataManager.getRam().getChannelName())
                    .addQueryParameter(IS_FROM_APP, "1")
                    .addQueryParameter(
                        OS_BUILD,
                        """${RxDeviceTool.getBuildBrandModel()},${RxDeviceTool.getSDKVersionName()},${RxAppTool.getAppVersionName(
                            BaseApp.getApp()
                        )}"""
                    )
                    .addQueryParameter(TS, (System.currentTimeMillis() / 1000).toString())
                    .addQueryParameter(
                        VERSION, RxAppTool.getAppVersionName(
                            BaseApp.getApp()
                        )
                    )

                val loginBean = ModularServiceManager.getPlatformUserService()?.getUser()
                if (loginBean != null) {
                    newBuilder.addQueryParameter(UID, loginBean.userId)
                              .addQueryParameter(TOKEN, loginBean.token)
                }

                it.proceed(request.newBuilder().url(newBuilder.build()).build())
            } else {
                it.proceed(request)
            }

        }
    }



    private data class Param(val name: String, val value: String)

    // 添加请求头
    private fun requestHead(appFrom: String): Interceptor {
        return Interceptor {
            val request = it.request()
            val body = request.body()
            val paramsString = StringBuilder()
            val params = ArrayList<Param>()
            if (body is FormBody) {
                (0 until body.size()).mapTo(destination = params) {
                    Param(
                        body.name(it),
                        body.value(it)
                    )
                }

            } else if (body is MultipartBody) {
                for (part in body.parts()) {
                    if ("text/plain; charset=utf-8" == part.body().contentType()!!.toString()) {
                        val headerStr = part.headers()!!.toString()
                        val name =
                            headerStr.split("\"\\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].split("=\"".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
                        val buffer = Buffer()
                        part.body().writeTo(buffer as BufferedSink)
                        val value = buffer.readUtf8()
                        params.add(Param(name, value))
                    }
                }
            }
            params.sortWith(Comparator { o1, o2 ->
                val res = o1.name.compareTo(o2.name)
                when {
                    res == 0 -> 0
                    res > 0 -> -1
                    else -> 1
                }
            })
            params.withIndex().forEach { (index, param) ->
                if (index != 0) paramsString.append("&")
                paramsString.append("${param.name}=${param.value}")
            }
            paramsString.append(SESSION_KEY)
            val head = "$YDL ${EncryptUtils.encryptMD5ToString(
                paramsString.toString()
            )}"

            val builder = it.request()
                .newBuilder()
                .header(AUTHORIZATION_NAME, head)
                .addHeader("Connection", "close")
                .addHeader(FFROM, PlatformDataManager.getRam().getChannelName())
                .addHeader(IS_FROM_APP, "1")
                .addHeader(VERSION, RxDeviceTool.getAppVersionName(BaseApp.getApp()))
                .addHeader(
                    OS_BUILD,
                    RxDeviceTool.getBuildMANUFACTURER() + "," + RxDeviceTool.getBuildBrandModel() + "," + RxDeviceTool.getOsBuileVersion() + "," + RxDeviceTool.getAppVersionName(
                        BaseApp.getApp()
                    )
                )
                .addHeader(OS_TYPE, "2")
                .addHeader(APP_NAME, appFrom)
            val loginBean =  ModularServiceManager.getPlatformUserService()?.getUser()
            if (loginBean != null) {
                builder.addHeader(TOKEN, loginBean.token)
                    .addHeader(UID, loginBean.userId)
            }
            it.proceed(builder.build())
        }
    }

    //初始化网络环境
    fun initEnv(c: Context, env: String) {
        var appEnv = env
        //判断是否使用上次缓存环境
        if (!TextUtils.isEmpty(YDLCacheUtils.getCacheApi())) {
            appEnv = YDLCacheUtils.getCacheApi()
        }

        val properties = Properties()

        //从properties文件中读取网络环境信息
        val inputStr = c.resources.openRawResource(com.ydl.ydlcommon.R.raw.api)
        properties.load(inputStr)
        inputStr.close()

        PHP_BASE_URL = properties.getProperty("serverurl.$appEnv")
        JAVA_BASE_URL = properties.getProperty("javaapi.$appEnv")

        ACTION_URL = properties.getProperty("actionurl.$appEnv")
        H5_URL = properties.getProperty("h5url.$appEnv")
        MH5_URL = properties.getProperty("mh5url.$appEnv")
        YDL_H5 = properties.getProperty("ydlh5url.$appEnv")
        WEB_URL = properties.getProperty("weburl.$appEnv")
        SERVER_TEMP_JAVA_URL = properties.getProperty("javatempurl.$appEnv")
        SERVER_API_JAVA_URL = properties.getProperty("javaurl.$appEnv")
        SERVER_COUPON_URL = properties.getProperty("javacouponurl.$appEnv")
    }

    private object Holder {
        val INSTANCE = HttpConfig()
    }
}