package com.gh.gamecenter.vpn

import android.content.Context
import android.os.Build
import android.os.ParcelFileDescriptor
import androidx.appcompat.app.AppCompatActivity
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.common.constant.Config
import com.gh.download.PackageObserver
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IVpnProvider
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.eventbus.EBPackage
import com.lightgame.utils.Utils
import java.util.*

object VpnHelper {

    private const val TAG = "VPN"
    private const val KEY_IS_FIRST_TIME_TO_SHOW_VPN_HINT_DIALOG = "is_first_time_to_show_vpn_hint_dialog"
    private const val KEY_IGNORED_VPN_HINT_DIALOG = "ignored_vpn_hint_dialog" // 忽略 VPN 提示弹窗
    private const val KEY_IGNORED_VPN_FUNCTION = "ignored_vpn_function" // 忽略 VPN 功能
    private const val STOP_VPN_COUNT_DOWN_INTERVAL = 30 * 1000L // 30 秒后自动停止 VPN 功能

    private var mCountDownTimer: Timer? = null
    private var mPfd: ParcelFileDescriptor? = null

    private val mVpnProvider by lazy {
        ARouter.getInstance().build(RouteConsts.provider.vpn).navigation() as? IVpnProvider
    }

    private var mPackageChangedListener: PackageObserver.PackageChangeListener? = null

    /**
     * 仅后台配置打开且手机系统大于 5.0 时才启用 VPN 功能
     */
    fun shouldUseVpn() = Config.isVpnOptionEnabled()
            && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
            && !SPUtils.getBoolean(KEY_IGNORED_VPN_FUNCTION, false)
            && mVpnProvider != null

    fun isTheFistTimeToShowVpnHintDialog() = SPUtils.getBoolean(KEY_IS_FIRST_TIME_TO_SHOW_VPN_HINT_DIALOG, true)

    /**
     * 标记 VPN 提示弹窗已显示
     */
    fun setVpnHintDialogShowed() = SPUtils.setBoolean(KEY_IS_FIRST_TIME_TO_SHOW_VPN_HINT_DIALOG, false)

    /**
     * 是否需要显示 VPN 提示弹窗
     */
    fun shouldShowVpnHintDialog() = !SPUtils.getBoolean(KEY_IGNORED_VPN_HINT_DIALOG, false)

    /**
     * 忽略 VPN 提示弹窗，不再询问
     */
    fun ignoreVpnHintDialog() = SPUtils.setBoolean(KEY_IGNORED_VPN_HINT_DIALOG, true)

    /**
     * 忽略 VPN 功能，不在启用
     */
    fun ignoreVpnFunction() = SPUtils.setBoolean(KEY_IGNORED_VPN_FUNCTION, true)

    fun isVpnPermissionGranted(activity: AppCompatActivity) = mVpnProvider?.isVpnPermissionGranted(activity)

    fun startVpn(activity: AppCompatActivity, onVpnStartedCallback: ((Boolean) -> Unit)) {
        val applicationContext = activity.applicationContext
        val packagesSet = Config.getNewApiSettingsEntity()?.install?.vpnRequired?.vpnMatchedPackagesName

        if (packagesSet.isNullOrEmpty()) {
            Utils.log(TAG, "vpn matched packages is empty, vpn is disabled")
            return
        }

        startVpn(activity, packagesSet, onVpnStartedCallback)

        mPackageChangedListener = PackageObserver.PackageChangeListener {
            if (it.type == EBPackage.TYPE_INSTALLED) {
                stopVpnIfNeeded(applicationContext)
            }
        }


        if (mCountDownTimer == null) {
            mCountDownTimer = Timer()
        }

        val task: TimerTask = object : TimerTask() {
            override fun run() {
                stopVpnIfNeeded(applicationContext)
            }
        }

        mCountDownTimer?.schedule(task, STOP_VPN_COUNT_DOWN_INTERVAL)

        PackageObserver.registerPackageChangeChangeListener(mPackageChangedListener!!)
    }

    private fun startVpn(
        activity: AppCompatActivity,
        noInternetConnectionPackageNameSet: HashSet<String>,
        onVpnStartedCallback: ((Boolean) -> Unit)
    ) {
        mVpnProvider?.startVpn(activity, noInternetConnectionPackageNameSet, onVpnStartedCallback) { pfd ->
            mPfd = pfd
        }
    }

    fun stopVpnIfNeeded(context: Context) {
        if (mPfd != null) {
            mVpnProvider?.stopVpn(context, mPfd)
            mPfd = null
        }

        mCountDownTimer?.cancel()
        mCountDownTimer = null

        mPackageChangedListener?.let {
            PackageObserver.unregisterPackageChangeChangeListener(it)
        }
        mPackageChangedListener = null
    }

}