package cn.yyxx.eyuangame.base

import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
import android.os.Build
import android.text.TextUtils
import android.webkit.WebView
import androidx.annotation.Keep
import cn.yyxx.eyuangame.Version
import cn.yyxx.eyuangame.base.entity.Function
import cn.yyxx.eyuangame.base.entity.SdkChargeInfo
import cn.yyxx.eyuangame.base.entity.SdkEvent
import cn.yyxx.eyuangame.base.entity.SdkRoleInfo
import cn.yyxx.eyuangame.base.internal.ICallback
import cn.yyxx.eyuangame.base.internal.IInitialize
import cn.yyxx.eyuangame.base.utils.Logger
import cn.yyxx.support.AppUtils

/**
 * @author #Suyghur.
 * Created on 2021/06/09
 */
class EYuanGame private constructor() {

    private var mSdkBridge: Any? = null
    private var processName: String = ""
    private var clickLoginTime = 0L
    private var clickLogoutTime = 0L
    private var clickChargeTime = 0L

    private var doSdkInit = false

    private fun getSdkBridgeManager(context: Context): Any? {
        if (mSdkBridge == null) {
            mSdkBridge = SdkBridgeManager.initSdkBridgeManager(context)
        }
        return mSdkBridge
    }

    /**
     * 同步Application中的attachBaseContext
     */
    fun attachBaseContext(application: Application, context: Context) {
        if (TextUtils.isEmpty(processName)) {
            this.processName = AppUtils.getProcessName(application)
        }
        if (TextUtils.isEmpty(processName) || processName != context.packageName) {
            return
        }
        if (mSdkBridge == null) {
            mSdkBridge = getSdkBridgeManager(application)
        }
        SdkBridgeManager.call(
            Function.ATTACH_BASE_CONTEXT,
            arrayOf(Application::class.java, Context::class.java),
            arrayOf(application, context)
        )
    }


    /**
     * 同步Application中的onCreate
     */
    fun initApplication(application: Application) {
        if (TextUtils.isEmpty(processName)) {
            this.processName = AppUtils.getProcessName(application)
        }
        //处理Android P webView的坑
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            try {
                if (application.packageName != processName) {
                    WebView.setDataDirectorySuffix(processName)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        if (TextUtils.isEmpty(processName) || processName != application.packageName) {
            return
        }
        if (mSdkBridge == null) {
            mSdkBridge = getSdkBridgeManager(application)
        }
        SdkBridgeManager.call(
            Function.INIT_APPLICATION,
            arrayOf(Application::class.java),
            arrayOf(application)
        )
    }

    /**
     * SDK初始化
     *
     * @param activity    Activity上下文
     * @param isLandscape 是否横屏
     * @param callback    SDK初始化回调
     */
    fun initialize(activity: Activity, isLandscape: Boolean, callback: ICallback) {
        if (checkSdkBridgeNull(Function.INITIALIZE, callback)) {
            return
        }

        //有些CP在资源再加时候回重复调用初始化，这里拦截一下
        if (doSdkInit) {
            Logger.e("Columbus initialize 已经执行，拦截此次调用")
            return
        }

        val initCallback = object : IInitialize {
            override fun onResult(code: Int, msg: String) {
                doSdkInit = code == 0
            }
        }

        SdkBridgeManager.call(
            Function.INITIALIZE,
            arrayOf(
                Activity::class.java,
                Boolean::class.java,
                ICallback::class.java,
                IInitialize::class.java
            ),
            arrayOf(activity, isLandscape, callback, initCallback)
        )
    }

    /**
     * SDK用户登录
     *
     * @param activity Activity上下文
     * @param isAutoLogin 是否自动登录
     * @param callback 登录回调对象
     */
    fun login(activity: Activity, isAutoLogin: Boolean, callback: ICallback) {
        if (checkSdkBridgeNull(Function.LOGIN, callback)) {
            return
        }

        if (checkSdkNonInit(Function.LOGIN, callback)) {
            return
        }

        if (System.currentTimeMillis() - clickLoginTime < CLICK_INTERVAL) {
            Logger.e("调用登录接口太频繁，拦截此次操作")
            return
        }

        clickLoginTime = System.currentTimeMillis()
        SdkBridgeManager.call(
            Function.LOGIN,
            arrayOf(Activity::class.java, Boolean::class.java, ICallback::class.java),
            arrayOf(activity, isAutoLogin, callback)
        )
    }

    /**
     * SDK用户登出账号
     *
     * @param activity Activity上下文
     * @param callback 登出回调对象
     */
    fun logout(activity: Activity, callback: ICallback) {
        if (checkSdkBridgeNull(Function.LOGOUT, callback)) {
            return
        }

        if (checkSdkNonInit(Function.LOGOUT, callback)) {
            return
        }

        if (System.currentTimeMillis() - clickLoginTime < CLICK_INTERVAL) {
            Logger.e("调用登录接口后，调用登出账号接口间隔太短，拦截此次操作")
            return
        }

        if (System.currentTimeMillis() - clickLogoutTime < CLICK_INTERVAL) {
            Logger.e("调用登出账号接口太频繁，拦截此次操作")
            return
        }

        clickLogoutTime = System.currentTimeMillis()
        SdkBridgeManager.call(
            Function.LOGOUT,
            arrayOf(Activity::class.java, ICallback::class.java),
            arrayOf(activity, callback)
        )
    }

    /**
     * SDK用户支付
     *
     * @param activity   Activity上下文
     * @param chargeInfo 支付信息实体对象
     * @param isIab      是否内购
     * @param callback   支付回调对象
     */
    fun charge(activity: Activity, chargeInfo: SdkChargeInfo, isIab: Boolean, callback: ICallback) {
        if (checkSdkBridgeNull(Function.CHARGE, callback)) {
            return
        }

        if (checkSdkNonInit(Function.CHARGE, callback)) {
            return
        }

        if (System.currentTimeMillis() - clickChargeTime < CLICK_INTERVAL) {
            Logger.e("调用充值接口太频繁，拦截此次操作")
            return
        }

        clickChargeTime = System.currentTimeMillis()
        SdkBridgeManager.call(
            Function.CHARGE,
            arrayOf(Activity::class.java, SdkChargeInfo::class.java, Boolean::class.java, ICallback::class.java),
            arrayOf(activity, chargeInfo, isIab, callback)
        )
    }

    /**
     * SDK角色创建信息上报
     *
     * @param activity Activity上下文
     * @param roleInfo 角色信息实体
     */
    fun roleCreate(activity: Activity, roleInfo: SdkRoleInfo) {
        if (checkSdkBridgeNull(Function.ROLE_CREATE, null)) {
            return
        }

        if (checkSdkNonInit(Function.ROLE_CREATE, null)) {
            return
        }

        SdkBridgeManager.call(
            Function.ROLE_CREATE,
            arrayOf(Activity::class.java, SdkRoleInfo::class.java),
            arrayOf(activity, roleInfo)
        )
    }

    /**
     * SDK角色登录信息上报
     *
     * @param activity Activity上下文
     * @param roleInfo 角色信息实体
     */
    fun roleLauncher(activity: Activity, roleInfo: SdkRoleInfo) {
        if (checkSdkBridgeNull(Function.ROLE_LAUNCHER, null)) {
            return
        }

        if (checkSdkNonInit(Function.ROLE_LAUNCHER, null)) {
            return
        }

        SdkBridgeManager.call(
            Function.ROLE_LAUNCHER,
            arrayOf(Activity::class.java, SdkRoleInfo::class.java),
            arrayOf(activity, roleInfo)
        )
    }

    /**
     * SDK角色升级信息上报
     *
     * @param activity Activity上下文
     * @param roleInfo 角色信息实体
     */
    fun roleLevelUp(activity: Activity, roleInfo: SdkRoleInfo) {
        if (checkSdkBridgeNull(Function.ROLE_LEVEL_UP, null)) {
            return
        }

        if (checkSdkNonInit(Function.ROLE_LEVEL_UP, null)) {
            return
        }

        SdkBridgeManager.call(
            Function.ROLE_LEVEL_UP,
            arrayOf(Activity::class.java, SdkRoleInfo::class.java),
            arrayOf(activity, roleInfo)
        )
    }

    /**
     * 显示退出框
     *
     * @param activity Activity上下文
     * @param callback 退出回调对象
     */
    fun openExitView(activity: Activity, callback: ICallback) {
        if (checkSdkBridgeNull(Function.OPEN_EXIT_VIEW, null)) {
            return
        }

        SdkBridgeManager.call(
            Function.OPEN_EXIT_VIEW,
            arrayOf(Activity::class.java, ICallback::class.java),
            arrayOf(activity, callback)
        )
    }

    fun onStart(activity: Activity) {
        if (checkSdkBridgeNull(Function.ON_START, null)) {
            return
        }

        SdkBridgeManager.call(Function.ON_START, arrayOf(Activity::class.java), arrayOf(activity))
    }

    fun onRestart(activity: Activity) {
        if (checkSdkBridgeNull(Function.ON_RESTART, null)) {
            return
        }

        SdkBridgeManager.call(Function.ON_RESTART, arrayOf(Activity::class.java), arrayOf(activity))
    }

    fun onResume(activity: Activity) {
        if (checkSdkBridgeNull(Function.ON_RESUME, null)) {
            return
        }

        SdkBridgeManager.call(Function.ON_RESUME, arrayOf(Activity::class.java), arrayOf(activity))
    }

    fun onPause(activity: Activity) {
        if (checkSdkBridgeNull(Function.ON_PAUSE, null)) {
            return
        }

        SdkBridgeManager.call(Function.ON_PAUSE, arrayOf(Activity::class.java), arrayOf(activity))
    }

    fun onStop(activity: Activity) {
        if (checkSdkBridgeNull(Function.ON_STOP, null)) {
            return
        }

        SdkBridgeManager.call(Function.ON_STOP, arrayOf(Activity::class.java), arrayOf(activity))
    }

    fun onDestroy(activity: Activity) {
        if (checkSdkBridgeNull(Function.ON_DESTROY, null)) {
            return
        }

        SdkBridgeManager.call(Function.ON_DESTROY, arrayOf(Activity::class.java), arrayOf(activity))
    }

    fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, intent: Intent) {
        if (checkSdkBridgeNull(Function.ON_ACTIVITY_RESULT, null)) {
            return
        }

        SdkBridgeManager.call(
            Function.ON_ACTIVITY_RESULT,
            arrayOf(Activity::class.java, Int::class.java, Int::class.java, Intent::class.java),
            arrayOf(activity, requestCode, resultCode, intent)
        )
    }

    fun onNewIntent(activity: Activity, intent: Intent) {
        if (checkSdkBridgeNull(Function.ON_NEW_INTENT, null)) {
            return
        }

        SdkBridgeManager.call(
            Function.ON_START,
            arrayOf(Activity::class.java, Intent::class.java),
            arrayOf(activity, intent)
        )
    }

    fun getCurrentUserId(): String {
        if (checkSdkBridgeNull(Function.GET_CURRENT_USER_ID, null)) {
            return ""
        }

        if (checkSdkNonInit(Function.GET_CURRENT_USER_ID, null)) {
            return ""
        }

        return SdkBridgeManager.callback(
            Function.GET_CURRENT_USER_ID,
            emptyArray(),
            emptyArray()
        ) as String
    }

    fun getSdkVersion(): String {
        return Version.VERSION_NAME
    }

    fun linkingEvent(context: Context, sdkEvent: SdkEvent) {
        if (checkSdkBridgeNull(Function.LINKING_EVENT, null)) {
            return
        }

        if (checkSdkNonInit(Function.LINKING_EVENT, null)) {
            return
        }
        SdkBridgeManager.call(Function.LINKING_EVENT, arrayOf(Context::class.java, SdkEvent::class.java), arrayOf(context, sdkEvent))
    }


    private fun checkSdkBridgeNull(function: String, callback: ICallback?): Boolean {
        return if (mSdkBridge == null) {
            Logger.e("invoke $function error ... SdkBridge is null")
            callback?.onResult(-1, "Columbus 初始化失败")
            true
        } else {
            false
        }
    }

    private fun checkSdkNonInit(function: String, callback: ICallback?): Boolean {
        return if (!doSdkInit) {
            Logger.e("invoke $function error ... EYuanGameSdk not initialized yet")
            callback?.onResult(-1, "EYuanGameSdk 还未进行初始化")
            true
        } else {
            false
        }
    }

    companion object {
        @JvmStatic
        @Keep
        fun getInstance(): EYuanGame {
            return ColumbusHolder.INSTANCE
        }

        private const val CLICK_INTERVAL: Int = 1500

        @Keep
        private object ColumbusHolder {
            val INSTANCE: EYuanGame = EYuanGame()
        }

        /**
         * 防止单例对象在反序列化时重新生成对象
         */
        @Keep
        private fun readResolve(): Any {
            return ColumbusHolder.INSTANCE
        }
    }
}