package cn.yyxx.eyuangame.core.network

import android.content.Context
import android.text.TextUtils
import cn.yyxx.eyuangame.base.utils.Logger
import cn.yyxx.eyuangame.core.entity.ResultInfo
import cn.yyxx.eyuangame.core.impl.SdkDrive
import cn.yyxx.eyuangame.core.internal.IRequestCallback
import cn.yyxx.support.JsonUtils
import cn.yyxx.support.StrUtils
import cn.yyxx.support.encryption.Base64Utils
import cn.yyxx.support.encryption.HexUtils
import cn.yyxx.support.encryption.Md5Utils
import cn.yyxx.support.volley.VolleySingleton
import cn.yyxx.support.volley.source.DefaultRetryPolicy
import cn.yyxx.support.volley.source.Response
import cn.yyxx.support.volley.source.VolleyError
import cn.yyxx.support.volley.source.toolbox.JsonObjectRequest
import org.json.JSONException
import org.json.JSONObject

/**
 * @author #Suyghur.
 * Created on 2021/06/21
 */
object VolleyRequest {

    private const val MAX_TIMEOUT = 10 * 1000

    fun post(context: Context, jsonObject: JSONObject, callback: IRequestCallback) {
        try {
            val time = System.currentTimeMillis().toString()
            val randomKey = time + StrUtils.getRandomString(16)
            val rawKey = Md5Utils.encodeByMD5(randomKey)
            val aesKey = Md5Utils.encodeByMD5(rawKey + StrUtils.reverseString(rawKey))
//            val p = AesUtils.encrypt(aesKey.substring(8, 24), jsonObject.toString())
            val hexP =
                SdkDrive.instance.invokeJob(context, aesKey.substring(8, 24), jsonObject.toString())
            val tmp = HexUtils.hexString2Bytes(hexP)
            val p = Base64Utils.encode(tmp)

            Logger.d("请求路由 : ${jsonObject["route_path"]}")
            Logger.d("请求参数 : $jsonObject")
            Logger.logHandler("请求路由 : ${jsonObject["route_path"]}\n")
            Logger.logHandler("请求参数 : $jsonObject\n")
            val obj = JSONObject()
            obj.put("p", p)
            obj.put("ts", rawKey)
            //TODO 拉起登录接口时会莫名其妙ANR，后续再排查
//            val json = SdkDrive.invokeJob(context, jsonObject.toString())
//            val obj = JSONObject(json)
//            //因为native c++中aes加密后生成的base64字符串可能会因为\0的原因被截断，所以使用hex进行编码
//            //得到json对象后将p内容由hex转为base64，然后再赋值回json对象中的p。
//            //ts因为是rsa加密，得到的base64字符串不会被截断，可能因为是长度远比aes生成的报文长度短
//            val hexP = obj.getString("p")
//            Logger.d("hex: $hexP")
//            val tmp = HexUtils.hexString2Bytes(hexP)
//            val base64P = Base64Utils.encode(tmp)
//            obj.put("p", base64P)

            val request = object : JsonObjectRequest(Method.POST, Host.HOST, obj, Response.Listener {
                val resultInfo = ResultInfo()
                resultInfo.code = -1
                resultInfo.msg = "接口请求异常"
                Logger.d(it)
                it?.apply {
                    try {
                        resultInfo.code = it.getInt("code")
                        resultInfo.msg = it.getString("msg")
                        resultInfo.data = if (JsonUtils.hasJsonKey(it, "data")) {
//                            //返回要对p进行base64 -> hex
//                            val responseObj = it.getJSONObject("data")
//                            val base64P2 = responseObj.getString("p")
//                            val tmp2 = Base64Utils.decode(base64P2)
//                            val hexP2 = HexUtils.bytes2HexString(tmp2)
//                            responseObj.put("p", hexP2)
//                            SdkDrive.parseJob(context, responseObj.toString())
                            parseResponse(context, it.getJSONObject("data"))
                        } else {
                            ""
                        }
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                }
                it.put("data", resultInfo.data)
                Logger.d("返回信息 : $it")
                Logger.logHandler("返回信息 : $it\n")
                callback.onResponse(resultInfo)
            }, Response.ErrorListener {
                it?.apply {
                    Logger.e("postByVolley onErrorResponse : $it")
                    callback.onResponse(getErrorResultInfo(it))
                }
            }) {
                override fun getHeaders(): MutableMap<String, String> {
                    val headers = HashMap<String, String>()
                    headers["Accept"] = "application/json"
                    headers["Content-Type"] = "application/json;charset=UTF-8"
                    return headers
                }
            }
            //设置超时时间
            request.retryPolicy = DefaultRetryPolicy(MAX_TIMEOUT, 1, 1.0f)
            VolleySingleton.getInstance(context.applicationContext)
                .addToRequestQueue(context.applicationContext, request)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun parseResponse(context: Context, data: JSONObject): String {
        try {
            val ts = data.getString("ts")
            val aesKey = Md5Utils.encodeByMD5(ts + StrUtils.reverseString(ts))
            val base64P = data.getString("p")
            val tmp = Base64Utils.decode(base64P)
            val p = HexUtils.bytes2HexString(tmp)
            return SdkDrive.instance.parseJob(context, aesKey.substring(8, 24), p)
        } catch (e: JSONException) {
            e.printStackTrace()
        }
        return ""
    }

    private fun getErrorResultInfo(volleyError: VolleyError): ResultInfo {
        val resultInfo = ResultInfo()
        resultInfo.code = 400
        resultInfo.msg = ""
        volleyError.networkResponse?.apply {
            resultInfo.code = statusCode
            if (!TextUtils.isEmpty(volleyError.message)) {
                resultInfo.msg = volleyError.message!!
            }
        }

        resultInfo.data = ""
        return resultInfo
    }
}