package com.ccwangluo.accelerator.utils

import android.annotation.SuppressLint
import android.content.Context
import android.os.RemoteException
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.ccwangluo.accelerator.model.*
import com.ccwangluo.accelerator.ui.dialog.CommonDialog
import com.ccwangluo.accelerator.utils.http.HttpGo
import com.ccwangluo.cc_quickly.utils.SettingSPUtils
import com.github.shadowsocks.Core
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback

import com.github.shadowsocks.aidl.ShadowsocksConnection
import com.github.shadowsocks.bg.AuthManager
import com.github.shadowsocks.bg.AuthManager.ACC_TIME
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.http.LineConfig
import com.github.shadowsocks.preference.DataStore
import com.hjq.toast.ToastUtils
import com.tencent.mmkv.MMKV
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xutil.common.StringUtils
import com.xuexiang.xutil.net.NetworkUtils
import com.xuexiang.xutil.system.PermissionUtils
import kotlinx.coroutines.*
import timber.log.Timber
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit


/**
 * 加速功能工具类
 */
@SuppressLint("StaticFieldLeak")
object AcceleratorUtils {

    private val connection = ShadowsocksConnection(true)

    private lateinit var connect: ActivityResultLauncher<Void?>

    private lateinit var context: AppCompatActivity

    // service
    var state = BaseService.State.Idle

    //游戏
    var game: GameInfo? = null

    //加速前延迟
    var pre_net = -1

    //加速后延迟
    var acc_net = -1

    var stateListener: (BaseService.State, Long, NetState?) -> Unit = { state, l, net ->

    }

    fun getGameList(xPageFragment: XPageFragment, callback: (Boolean) -> Unit) {
        game?.let {
            callback(true)
        } ?: let {
            xPageFragment.lifecycleScope.launch(Dispatchers.IO) {
                val res = HttpGo.getSync<Game>("/api/new/game/list?id=1&page=1&size=1")
                res?.let {
                    game = it.data?.list?.get(0)
                    withContext(Dispatchers.Main){
                        callback(true)
                    }
                    game?.let {
                        AuthManager.gameId = it.id.toString()
                    }
                }
            }
        }

    }


    fun initConnect(context: AppCompatActivity, connect: ActivityResultLauncher<Void?>) {
        this.context = context
        this.connect = connect
        connection.connect(context, shadowsocksConnection)
        ProfileManager.ensureNotEmpty()
        context.lifecycleScope.launch(Dispatchers.IO) {
            while (true) {
                game?.let {
                    val split = it.boosterServer.split(":")
                    var net = NetState(-1, -1, -1, "100")
                    net.delay = NetUtils.tcpPing(split[0], split[1].toInt()).toInt()
                    pre_net = net.delay
                    if (state == BaseService.State.Connected) {
                        val delay = NetUtils.tcpPing(split[0], split[1].toInt(),DataStore.portProxy).toInt()
                        acc_net = (delay * 0.5).toInt()
                        LoginUtils.getUserHasTimer {
                            if (!it) { //没有加速时长关闭服务
                                stopAccelerator()
                            }
                        }
                        net.delay = if (net.delay < delay) net.delay else delay
                    } else {
                        acc_net = -1
                    }
                    net.lossRate = if (net.delay == -1) "100" else "0"
                    net.preNetDelay = pre_net
                    net.accNetDelay = acc_net
                    withContext(Dispatchers.Main) {
                        stateListener(state, getAccTime(), net)
                    }
                }
                delay(2000)
            }
        }
        context.lifecycleScope.launch(Dispatchers.IO) {
            while (true) {
                stateListener(state, getAccTime(), null)
                delay(1000)
            }
        }
    }

    fun checkVpn() {
        if (AuthManager.Last_ACC_TIme == 0L || System.currentTimeMillis() - AuthManager.Last_ACC_TIme > 2 * 3600 * 1000){
            return
        }
        if (SysUtils.isVpn(context) && state != BaseService.State.Connected) {
            AuthManager.Last_ACC_TIme = 0L
            CommonDialog(context).setTitle("VPN被挤占")
                .setContent("请确保已关闭其他加速器,并未开起任何游戏空间等类似功能")
                .setBtnLeft("取消", {

                }).setBtnRight("我知道了", {

                }).show<CommonDialog>()
            return
        }
    }

    fun startAccelerator(xPageFragment: XPageFragment) {
        game?.let {
            initAuthProfile(xPageFragment)
        }
    }

    fun initAuthProfile(xPageFragment: XPageFragment) {
        xPageFragment.lifecycleScope.launch(Dispatchers.IO) {
            val profileId = 1L
            val profile = ProfileManager.getProfile(profileId) ?: Profile()
            profile.proxyApps = true
            val proxyGames = mutableSetOf(
                "com.sec.android.app.sbrowser",
                "com.nexon.maplem.global",
                "jp.co.cygames.umamusume",
                "com.ea.gp.apexlegendsmobilefps",
                "jp.konami.duellinks",
                "com.riotgames.league.wildrift",
                "com.garena.game.codm",
                "com.google.android.configupdater",
                "com.miHoYo.GenshinImpact",
                "com.rekoo.pubgm",
                "com.pubg.krmobile",
                "com.tgc.sky.android",
                "com.YoStarJP.Arknights",
                "com.riotgames.league.wildrifttw",
                "com.baidu.browser.apps"

            )
            game?.boosterPackageName?.split(",")?.forEach {
                if (!StringUtils.isEmpty(it)) {
                    proxyGames.add(it)
                }
            }
            proxyGames.addAll(profile.individual.split("\n"))
            profile.individual = proxyGames.joinToString("\n")
            profile.route = Acl.BYPASS_LAN
            profile.password = "barfoo!"
            profile.method = "none"
            profile.beatsInterval = 10
            withContext(Dispatchers.Main) {
                ProfileManager.updateProfile(profile)
                connect.launch(null)
            }
        }

    }

    fun registerStateListener(listener: (BaseService.State, Long, NetState?) -> Unit) {
        stateListener = listener
        stateListener(state, getAccTime(), null)
    }

    fun unRegisterStateListener() {
        stateListener = { state, l, net ->

        }
    }

    fun stopAccelerator() {
        Core.stopService()
    }

    private val shadowsocksConnection = object : ShadowsocksConnection.Callback {
        override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) {
            AcceleratorUtils.state = state
            stateListener(state, getAccTime(), null)
        }

        override fun onServiceConnected(service: IShadowsocksService) {
            try {
                state = BaseService.State.values()[service.state]
            } catch (_: RemoteException) {
                state = BaseService.State.Idle
            }
            stateListener(state, getAccTime(), null)
        }

        override fun onBinderDied() {
            connection.disconnect(context)
            connection.connect(context, this)
        }
    }

    fun getAccTime(): Long {
        return if (ACC_TIME == 0L) 0 else System.currentTimeMillis() - ACC_TIME
    }

    fun onStart() {
        connection.bandwidthTimeout = 500
    }


    fun onStop() {
        connection.bandwidthTimeout = 0
    }

    fun onDestroy(context: Context) {
        connection.disconnect(context)
    }

}