package com.lanyun.wanglaotou.util

import android.text.TextUtils
import android.util.Log
import com.lanyun.wanglaotou.AppConfig
import com.lanyun.wanglaotou.R
import com.lanyun.wanglaotou.dao.EConfigType
import com.lanyun.wanglaotou.dao.ServerConfig
import com.lanyun.wanglaotou.dao.ServersCache
import com.lanyun.wanglaotou.dao.V2rayConfig.Companion.DEFAULT_SECURITY
import com.lanyun.wanglaotou.dao.V2rayConfig.Companion.TLS
import com.lanyun.wanglaotou.model.NodeModel
import com.lanyun.wanglaotou.model.UserModel
import com.tencent.mmkv.MMKV
import java.net.URI

object AngConfigManager {
    private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
    private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
    private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) }
    private val subStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SUB, MMKV.MULTI_PROCESS_MODE) }

  //  var serverList = MmkvManager.decodeServerList()
    val serversCache = mutableListOf<ServersCache>()

    //var serversCacheNode = mutableListOf<NodeModel>()

    fun removeCache() {
        serversCache.clear()
        MmkvManager.removeAllServer()
    }

//    fun updateServersCacheNode(a : List<NodeModel>)
//    {
//        serversCacheNode = a.toMutableList()
//    }

    fun updateSelect(gui:String){
        mainStorage?.encode(MmkvManager.KEY_SELECTED_SERVER, gui)
    }

    fun importConfig(nodeModel: NodeModel, uuid: String, removedSelectedServer: ServerConfig?,cache:Boolean = false): Int {
        try {
            var config: ServerConfig? = null
            val allowInsecure = settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
            if (nodeModel.type == "v2ray") {
                config = ServerConfig.create(EConfigType.VMESS)
                val streamSetting = config.outboundBean?.streamSettings ?: return -1
                var allowInsecure = false
                if (nodeModel.tlsSettings != null){
                    allowInsecure  = nodeModel.tlsSettings.allowInsecure.toBoolean()
                }
//                val (_, protocol) =
//                    Regex("(tcp|http|ws|kcp|quic|grpc)(\\+tls)?:([0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12})")
//                        .matchEntire(nodeModel.network)?.groupValues
//                        ?: error("parse user info fail.")
                val tls = nodeModel.tls
                val alterId = 0
                config.remarks = Utils.urlDecode(nodeModel.name ?: "")
                config.outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
                    vnext.address =nodeModel.host
                    vnext.port = nodeModel.port
                    vnext.users[0].id = uuid
                    vnext.users[0].security = DEFAULT_SECURITY
                    vnext.users[0].alterId = alterId
                }
                val fingerprint = streamSetting.tlsSettings?.fingerprint
                if (nodeModel.tlsSettings != null){
                    val servicename = nodeModel.tlsSettings.serverName

                    val sni = streamSetting.populateTransportSettings(nodeModel.network, "",
                        "",
                        "", "", "",
                        "", "", servicename)
                    streamSetting.populateTlsSettings(if (tls == 1) TLS else "", allowInsecure, sni, fingerprint, null)
                } else {
                    streamSetting.populateTlsSettings(if (tls == 1) TLS else "", allowInsecure, "", fingerprint, null)
                }
            } else if(nodeModel.type == "shadowsocks") {
                config = ServerConfig.create(EConfigType.SHADOWSOCKS)
                config.remarks = Utils.urlDecode(nodeModel.name ?: "")
                config.outboundBean?.settings?.servers?.get(0)?.let { server ->
                    server.address = nodeModel.host
                    server.port = nodeModel.port
                    server.password = uuid
                    server.method = nodeModel.cipher ?: ""
                }
            } else if(nodeModel.type ==  "trojan") {
                config = ServerConfig.create(EConfigType.TROJAN)
                config.remarks = Utils.urlDecode(nodeModel.name ?: "")
                val fingerprint = config.outboundBean?.streamSettings?.tlsSettings?.fingerprint
                if (nodeModel.tlsSettings != null){
                    val servicename = nodeModel.tlsSettings.serverName

                    val sni = config.outboundBean?.streamSettings?.populateTransportSettings("tcp" ?: "tcp", "",
                        "", "", "", "", "",
                        "", servicename)
                    if (sni != null) {
                        config.outboundBean?.streamSettings?.populateTlsSettings(TLS, allowInsecure, sni, fingerprint,null)
                    }
                } else {
                    config.outboundBean?.streamSettings?.populateTlsSettings(TLS, allowInsecure, "", fingerprint, null)
                }

                config.outboundBean?.settings?.servers?.get(0)?.let { server ->
                    server.address = nodeModel.host
                    server.port = nodeModel.port
                    server.password = uuid

                }
            }

            if (config == null){
                return R.string.toast_incorrect_protocol
            }




            val guid = MmkvManager.encodeServerConfig("",config)
            if (cache){
                serversCache.add(ServersCache(guid,nodeModel,config))
            }

            Log.e(AppConfig.ANG_PACKAGE,"gui--${guid}---config${config.remarks}")

//            if (select){
//                mainStorage?.encode(MmkvManager.KEY_SELECTED_SERVER, guid)
//            }
//            if (removedSelectedServer != null &&
//                config.getProxyOutbound()?.getServerAddress() == removedSelectedServer.getProxyOutbound()?.getServerAddress() &&
//                config.getProxyOutbound()?.getServerPort() == removedSelectedServer.getProxyOutbound()?.getServerPort()) {
//
//            }


        }
        catch (e: Exception) {
            e.printStackTrace()
            return -1
        }
        return 0
    }


}