package com.ccwangluo.accelerator.utils.http

import com.ccwangluo.accelerator.model.BaseModel
import com.ccwangluo.accelerator.utils.LoginUtils
import com.ccwangluo.accelerator.utils.datareport.BaseData
import com.github.shadowsocks.http.HttpConfig
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hjq.toast.ToastUtils
import com.xuexiang.xutil.XUtil
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.io.IOException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import java.util.logging.Level
import java.util.logging.Logger
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager


object HttpGo {
    val okHttpClient: OkHttpClient
    val gson: Gson

    val TAG = HttpGo::class.java.name

    init {
        okHttpClient = OkHttpClient().newBuilder()
            .readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
            .writeTimeout(60, TimeUnit.SECONDS)//设置写的超时时间
            .connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
            //https支持
            .hostnameVerifier { hostname, session -> true }
            .sslSocketFactory(initSSLSocketFactory(), initTrustManager())
            .build()
        gson = Gson()
        Logger.getLogger(OkHttpClient::class.java.getName()).setLevel(Level.FINE)

    }

    fun getClient(): OkHttpClient {
        return okHttpClient;
    }

    inline fun <reified T> getSync(url: String): BaseModel<T>? {
        try {
            val request = Request.Builder()
                .url(HttpConfig.baseUrl + url)
                .get()

            LoginUtils.token?.let {
                request.addHeader("Authorization", it)
            }
            Timber.i("%s%s", url, request.toString())
            val call = okHttpClient.newCall(request.build())
            val response: Response = call.execute()
            if (response.isSuccessful) {
                val type = object : TypeToken<BaseModel<T>>() {}.type
                val string = response.body?.string()
                Timber.i("getSync:" + string.toString())
                val result: BaseModel<T>? = gson.fromJson(string, type)
                return result
            } else if (response.code == 401) {
                LoginUtils.clearToken()
                LoginUtils.login(XUtil.getContext(), {})
            } else {
                ToastUtils.show("网络错误")
            }
        } catch (e: java.lang.Exception) {
            ToastUtils.show("网络错误")

        }
        return null
    }


    val jsonType get() = "application/json; charset=utf-8".toMediaTypeOrNull()


    /**
     * 同步请求
     */
    inline fun <reified T> postSync(
        url: String,
        param: MutableMap<String, out Any>
    ): BaseModel<T>? {
        try {
            val body: RequestBody = gson.toJson(param).toString().toRequestBody(jsonType)
            val request = Request.Builder()
                .url(HttpConfig.baseUrl + url)
                .post(body)
            LoginUtils.token?.let {
                request.addHeader("Authorization", it)
            }
            Timber.i(request.toString())
            val call = okHttpClient.newCall(request.build())
            val response: Response = call.execute()
            if (response.isSuccessful) {
                val string = response.body?.string()
                Timber.i("postSync:" + string.toString())
                val type = object : TypeToken<BaseModel<T>>() {}.type
                val result: BaseModel<T>? = gson.fromJson(string, type)
                return result
            } else if (response.code == 401) {

                LoginUtils.clearToken()
                LoginUtils.login(XUtil.getContext(), {})

            } else {
                ToastUtils.show("网络错误")
            }
        } catch (e: java.lang.Exception) {
            ToastUtils.show("网络错误")
        }
        return null
    }

    /**
     * 异步请求 (专用于数据上报)
     */
    fun postDataASync(url: String, param: MutableSet<BaseData>, callback: (Boolean) -> Unit) {
        try {
            val prebody = gson.toJson(param).toString()
            Timber.i("pre postDataASync:%s", prebody)
            val body: RequestBody = prebody.toRequestBody(jsonType)
            val request = Request.Builder()
                .url(url)
                .post(body)
            val call = okHttpClient.newCall(request.build())
            call.enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    callback(false)
                }

                override fun onResponse(call: Call, response: Response) {
                    var result = response.body?.string()
                    Timber.i("success postDataASync:%s", result)
                    callback(true)
                }

            })
        } catch (e: java.lang.Exception) {
            Timber.i("error postASync:" + e)
        }
    }


    private fun initSSLSocketFactory(): SSLSocketFactory {
        var sslContext: SSLContext? = null
        try {
            sslContext = SSLContext.getInstance("SSL")
            val xTrustArray = arrayOf(initTrustManager())
            sslContext.init(
                null,
                xTrustArray, SecureRandom()
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }


        return sslContext!!.socketFactory
    }

    private fun initTrustManager(): X509TrustManager {
        return object : X509TrustManager {
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }

            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }

            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }
        }
    }

}
