package com.ccwangluo.accelerator.utils.http

import com.ccwangluo.accelerator.model.BaseModel
import com.ccwangluo.accelerator.utils.LoginUtils
import com.github.shadowsocks.http.HttpConfig
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hjq.toast.ToastUtils
import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
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()

    }

    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("%s%s", url, string.toString())
                return gson.fromJson(string, type)
            } 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, String>): 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(string.toString())
                val type = object : TypeToken<BaseModel<T>>() {}.type
                return gson.fromJson(string, type)
            }
        } catch (e: java.lang.Exception) {
            ToastUtils.show("网络错误")
        }
        return null
    }


    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?) {
            }
        }
    }

}
