package com.ccwangluo.accelerator.utils.http

import com.ccwangluo.accelerator.model.BaseModel
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hjq.toast.ToastUtils
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.IOException
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

    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): T? {
        val request: Request = Request.Builder()
            .url(HttpConfig.baseUrl + url)
            .get()
            .build()
        val call = okHttpClient.newCall(request)
        val response: Response = call.execute()
        if (response.isSuccessful) {
            return gson.fromJson(response.body?.string(), T::class.java)
        } else {
            ToastUtils.show("网络错误")
            return null
        }
    }


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

    /**
     * 异步请求
     */
    inline fun <reified T> postASync(
        url: String,
        param: MutableMap<String, String>,
        crossinline callback: (T) -> Unit
    ) {
        val body: RequestBody = gson.toJson(param).toString().toRequestBody(jsonType)
        val request: Request = Request.Builder()
            .url(HttpConfig.baseUrl + url)
            .post(body)
            .build()
        val call = okHttpClient.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                ToastUtils.show("网络错误")
            }

            override fun onResponse(call: Call, response: Response) {
                callback(gson.fromJson(response.body?.string(), T::class.java))
            }
        })
    }

    /**
     * 同步请求
     */
    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 = Request.Builder()
                .url(HttpConfig.baseUrl + url)
                .post(body)
                .build()
            val call = okHttpClient.newCall(request)
            val response: Response = call.execute()
            println(response)
            if (response.isSuccessful) {
                val string = response.body?.string()
                println(string)
                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?) {
            }
        }
    }
}
