package com.vpn.fastestvpnservice.helpers

import android.app.Activity
import android.content.Context
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.Drawable
import android.util.Log
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.vpn.fastestvpnservice.R
import com.vpn.fastestvpnservice.beans.*
import com.vpn.fastestvpnservice.constants.AppEnum

class BasePreferenceHelper(private val context: Context) : PreferencesHelper() {

    fun clearAllData() {
        removePreference(context, KEY_FILENAME, KEY_USER)
        removePreference(context, KEY_FILENAME, KEY_USER_PASSWORD)
        removePreference(context, KEY_FILENAME, KEY_SERVERS_DATA)
//        removePreference(context, KEY_FILENAME, KEY_SERVERS)
        removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS)
        removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN)
        removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW)
        removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL)
        removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV)
        removePreference(context, KEY_FILENAME, PROTOCOL)
        removePreference(context, KEY_FILENAME, X_PLATFORM_TOKEN)
        removePreference(context, KEY_FILENAME, KEY_PRODUCT)
        removePreference(context, KEY_FILENAME, KEY_AVAILABLE_PROTOCOLS)
        removePreference(context, KEY_FILENAME, KEY_ENABLED_PROTOCOLS)
        removePreference(context, KEY_FILENAME, KEY_WIREGUARD)
        removePreference(context, KEY_FILENAME, KEY_FEATURES_DATA)
        removePreference(context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV)
        removePreference(context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV)
        removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY)
        removePreference(context, KEY_FILENAME, TV_SPLIT_CLASS)
        removePreference(context, KEY_FILENAME, KEY_ADBLOCK_SWITCH)
        removePreference(context, KEY_FILENAME, KEY_ISLOGGEDIN)
    }

    fun saveUser(user: UserResponse) {
        putStringPreference(context, KEY_FILENAME, KEY_USER, Gson().toJson(user))
    }

    fun getUser(): UserResponse? {
        return Gson().fromJson<UserResponse>(
            getStringPreference(context, KEY_FILENAME, KEY_USER), UserResponse::class.java
        )
    }

    fun saveProduct(product: Product) {
        putStringPreference(context, KEY_FILENAME, KEY_PRODUCT, Gson().toJson(product))
    }

    fun getProduct(): Product? {
        return Gson().fromJson<Product>(
            getStringPreference(context, KEY_FILENAME, KEY_PRODUCT), Product::class.java
        )
    }

    fun saveWireGuard(wireGuard: WireGuard) {
        putStringPreference(context, KEY_FILENAME, KEY_WIREGUARD, Gson().toJson(wireGuard))
    }

    fun getWireGuard(): WireGuard? {
        return Gson().fromJson<WireGuard>(
            getStringPreference(context, KEY_FILENAME, KEY_WIREGUARD), WireGuard::class.java
        )
    }

    fun saveIpInfo(ipInfo: IpInfo) {
        putStringPreference(context, KEY_FILENAME, KEY_IPINFO, Gson().toJson(ipInfo))
    }

    fun getIpinfo(): IpInfo? {
        return Gson().fromJson<IpInfo>(
            getStringPreference(context, KEY_FILENAME, KEY_IPINFO), IpInfo::class.java
        )
    }

    fun savePassword(pass: String) {
        putStringPreference(context, KEY_FILENAME, KEY_USER_PASSWORD, pass)
    }

    fun getPassword(): String {
        return getStringPreference(context, KEY_FILENAME, KEY_USER_PASSWORD)
    }

    fun saveServerData(list: ArrayList<ServerData>) {
        putStringPreference(context, KEY_FILENAME, KEY_SERVERS_DATA, Gson().toJson(list))
    }

    fun getServerData(): List<ServerData> {
        val type = object : TypeToken<List<ServerData?>?>() {}.type
        return Gson().fromJson<List<ServerData>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_SERVERS_DATA
            ), type
        )
    }

    fun saveFeaturesData(list: ArrayList<ProductFeatures>) {
        putStringPreference(context, KEY_FILENAME, KEY_FEATURES_DATA, Gson().toJson(list))
    }

    fun getFeaturesData(): List<ProductFeatures> {
        val type = object : TypeToken<List<ProductFeatures?>?>() {}.type
        return Gson().fromJson<List<ProductFeatures>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_FEATURES_DATA
            ), type
        )
    }

    fun saveEnabledProtocols(list: ArrayList<String>) {
        putStringPreference(context, KEY_FILENAME, KEY_ENABLED_PROTOCOLS, Gson().toJson(list))
    }

    fun getEnabledProtocols(): ArrayList<String> {
        val type = object : TypeToken<ArrayList<String?>?>() {}.type
        try {
            return Gson().fromJson<ArrayList<String>>(
                getStringPreference(
                    context, KEY_FILENAME, KEY_ENABLED_PROTOCOLS
                ), type
            )
        }
        catch (e: Exception) {
            val tempList = ArrayList<String>()
            tempList.add("WG")
            tempList.add("IKEV2")
            tempList.add("TCP")
            tempList.add("UDP")

            return tempList
        }

    }

    fun saveAvailableProtocols(list: ArrayList<String>) {
        var tempList = ArrayList<String>()

        if (list.contains(AppEnum.WG_PROTOCOL.key)) {
            tempList.add(AppEnum.WG_PROTOCOL.key)
        }
        if (list.contains(AppEnum.IKEV2_PROTOCOL.key)) {
            tempList.add(AppEnum.IKEV2_PROTOCOL.key)
        }
        if (list.contains(AppEnum.TCP_PROTOCOL.key)) {
            tempList.add(AppEnum.TCP_PROTOCOL.key)
        }
        if (list.contains(AppEnum.UDP_PROTOCOL.key)) {
            tempList.add(AppEnum.UDP_PROTOCOL.key)
        }

        putStringPreference(context, KEY_FILENAME, KEY_AVAILABLE_PROTOCOLS, Gson().toJson(tempList))
    }

    fun getAvailableProtocols(): ArrayList<String> {
        val type = object : TypeToken<ArrayList<String?>?>() {}.type
        return try {
            Gson().fromJson<ArrayList<String>>(
                getStringPreference(
                    context, KEY_FILENAME, KEY_AVAILABLE_PROTOCOLS
                ), type
            )
        } catch (e: Exception) {
            val tempList = ArrayList<String>()
            tempList.add("WG")
            tempList.add("IKEV2")
            tempList.add("TCP")
            tempList.add("UDP")

            return tempList
        }

    }

    fun getEnableTvAppsSplit(): ArrayList<TvEnableApps>? {

        val type = object : TypeToken<ArrayList<TvEnableApps?>?>() {}.type
        return Gson().fromJson<ArrayList<TvEnableApps>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV
            ), type
        )
    }

    fun setEnableTvAppsSplit(allSplitTunnelEnabled: ArrayList<TvEnableApps>?) {
        if (allSplitTunnelEnabled == null) {
            removePreference(context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV, Gson().toJson(allSplitTunnelEnabled))
    }

    fun getDisableTvAppsSplit(): ArrayList<TvDisableApps>? {

        val type = object : TypeToken<ArrayList<TvDisableApps?>?>() {}.type
        return Gson().fromJson<ArrayList<TvDisableApps>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV
            ), type
        )
    }

    fun setDisableTvAppsSplit(allSplitTunnelEnabled: ArrayList<TvDisableApps>?) {
        if (allSplitTunnelEnabled == null) {
            removePreference(context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV, Gson().toJson(allSplitTunnelEnabled))
    }

    fun getSplitTunnelTvAppsName(): ArrayList<String>? {

        val type = object : TypeToken<ArrayList<String?>?>() {}.type
        return Gson().fromJson<ArrayList<String>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_SPLIT_TUNNEL
            ), type
        )
    }

    fun setSplitTunnelTvAppsName(allSplitTunnelEnabled: ArrayList<String>?) {
        if (allSplitTunnelEnabled == null) {
            removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL, Gson().toJson(allSplitTunnelEnabled))
    }

    fun getSplitTunnelTvAppsPackageName(): ArrayList<String>? {

        val type = object : TypeToken<ArrayList<String?>?>() {}.type
        return Gson().fromJson<ArrayList<String>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV
            ), type
        )
    }

    fun setSplitTunnelTvAppsPackageName(allSplitTunnelEnabled: ArrayList<String>?) {
        if (allSplitTunnelEnabled == null) {
            removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV, Gson().toJson(allSplitTunnelEnabled))
    }

    fun getSplitTunnelTvAppsEntry(): ArrayList<String>? {

        val type = object : TypeToken<ArrayList<String?>?>() {}.type
        return Gson().fromJson<ArrayList<String>>(
            getStringPreference(
                context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY
            ), type
        )
    }

    fun setSplitTunnelTvAppsEntry(appsEntry: ArrayList<String>?) {
        if (appsEntry == null) {
            removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY, Gson().toJson(appsEntry))
    }

    fun setInstanceActivity(activity: Activity){
        putStringPreference(context, KEY_FILENAME, KEY_ACTIVITY, Gson().toJson(activity))

    }

    fun getInstanceActivity(): Activity? {
        var activity: Activity? = null
        val mainActivity = getStringPreference(context, KEY_FILENAME, KEY_ACTIVITY)
        if (mainActivity != null){
            val gson = GsonBuilder().create()
            activity = gson.fromJson(mainActivity, Activity::class.java)
        }
        return activity
    }

    fun getServerObject(): Server? {
        var serverObj: Server? = null
        val serverObjStr: String = getStringPreference(context, KEY_FILENAME, KEY_SERVERS)
        if (serverObjStr != null) {
            val gson = GsonBuilder().create()
            serverObj = gson.fromJson(serverObjStr, Server::class.java)
        }
        return serverObj
    }

    fun setServerObject(serverObj: Server?) {
        putStringPreference(context, KEY_FILENAME, KEY_SERVERS, Gson().toJson(serverObj))
    }

    fun getSplitTunneledApps(): String? {
        return getStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS)
    }

    fun setSplitTunneledApps(selectedApps: String?) {
        if (selectedApps == null) {
            removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS, selectedApps)
    }

    fun getSplitTunneledAppsNoVpn(): String? {
        return getStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN)
    }

    fun setSplitTunneledAppsNoVpn(selectedApps: String?) {
        if (selectedApps == null) {
            removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN, selectedApps)
    }

    fun getSplitTunneledAppsNotAllow(): String? {
        return getStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW)
    }

    fun setSplitTunneledAppsNotAllow(selectedApps: String?) {
        if (selectedApps == null) {
            removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW)
            return
        }
        putStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW, selectedApps)
    }

    fun saveAppDetails(appDetails: String) {
        putStringPreference(context, KEY_FILENAME, APP_DETAILS, appDetails)
    }

    fun getAppDetails(): String {
        return getStringPreference(context, KEY_FILENAME, APP_DETAILS)
    }

    fun saveFileDetails(fileDetails: String) {
        putStringPreference(context, KEY_FILENAME, FILE_DETAILS, fileDetails)
    }

    fun getFileDetails(): String {
        return getStringPreference(context, KEY_FILENAME, FILE_DETAILS)
    }


    fun saveTvSplitTunnel(tvSplitTunneling: ArrayList<TvSplitTunneling>) {
        putStringPreference(context, KEY_FILENAME, TV_SPLIT_CLASS, Gson().toJson(tvSplitTunneling))
    }

    fun getTvSplitTunnel(): ArrayList<TvSplitTunneling> {
        val tvSplitTunneling = Gson().fromJson<ArrayList<TvSplitTunneling>>(
            getStringPreference(context, KEY_FILENAME, TV_SPLIT_CLASS), TvSplitTunneling::class.java
        )
        return tvSplitTunneling
    }

    fun saveProtocol(protocol: Protocol) {
        putStringPreference(context, KEY_FILENAME, PROTOCOL, Gson().toJson(protocol))
    }

    fun getProtocol(): Protocol {
        var protocol = Gson().fromJson<Protocol>(
            getStringPreference(context, KEY_FILENAME, PROTOCOL), Protocol::class.java
        )
        protocol?.let {
            return protocol
        } ?: kotlin.run {
            return Protocol(
                AppEnum.WG_PROTOCOL.title, AppEnum.WG_PROTOCOL.key, 1
//                AppEnum.AUTO_PROTOCOL.title, AppEnum.IKEV2_PROTOCOL.key, 0
            ) //By default (AUTO) Protocol is selected (index 0 = AUTO). Checking IKEV2 first then check TCP/UDP
        }
    }

    fun saveRadioBtnSplitPos(position: Int) {
        putIntegerPreference(context, KEY_FILENAME, KEY_SPLIT_POS, position)
    }

    fun getRadioBtnSplitPos(): Int {
        return getIntegerPreference(context, KEY_FILENAME, KEY_SPLIT_POS)
    }

    fun saveAdBlockState(status: Boolean) {
        putBooleanPreference(context, KEY_FILENAME, KEY_ADBLOCK_SWITCH, status)
    }

    fun getAdBlockState(): Boolean {
        return getBooleanPreference(context, KEY_FILENAME, KEY_ADBLOCK_SWITCH)
    }

    fun saveFcmToken(token: String) {
        putStringPreference(context, KEY_FILENAME, KEY_FCM, token)
    }

    fun getLoggedInState(): Boolean {
        return getBooleanPreference(context, KEY_FILENAME, KEY_ISLOGGEDIN)
    }

    fun setLoggedInState(state: Boolean) {
        putBooleanPreference(context, KEY_FILENAME, KEY_ISLOGGEDIN, state)
    }

    fun getFcmToken(): String {
        return getStringPreference(context, KEY_FILENAME, KEY_FCM)
    }

    fun saveXPlatformToken(token: String) {
        putStringPreference(context, KEY_FILENAME, X_PLATFORM_TOKEN, token)
    }

    fun getXPlatformToken(): String {
        return getStringPreference(context, KEY_FILENAME, X_PLATFORM_TOKEN)
    }

    companion object {
        private const val KEY_FILENAME = "file_fastestvpn"
        private const val KEY_USER = "keydata_user"
        private const val KEY_PRODUCT = "keydata_product"
        private const val KEY_WIREGUARD = "keydata_wireguard"
        private const val KEY_IPINFO = "keydata_ipinfo"
        private const val KEY_USER_PASSWORD = "keydata_user_password"
        private const val KEY_SERVERS_DATA = "keydata_servers_data"
        private const val KEY_FEATURES_DATA = "keydata_features_data"
        private const val KEY_ENABLED_PROTOCOLS = "keydata_enabled_protocols"
        private const val KEY_AVAILABLE_PROTOCOLS = "keydata_available_protocols"
        private const val KEY_SERVERS = "keydata_server"
        private const val KEY_SELECTED_APPS = "keydata_selectedApps"
        private const val KEY_SELECTED_APPS_NO_VPN = "keydata_selectedAppsNoVpn"
        private const val KEY_SELECTED_APPS_NOT_ALLOW = "keydata_selectedAppsNotAllow"
        private const val KEY_SPLIT_TUNNEL = "keydata_tv_apps_name"
        private const val KEY_SPLIT_TUNNEL_TV = "keydata_tv_apps_package_name"
        private const val KEY_SPLIT_ENABLE_TV = "keydata_tv_apps_enable"
        private const val KEY_SPLIT_DISABLE_TV = "keydata_tv_apps_disable"
        private const val KEY_SPLIT_TUNNEL_ENTRY = "keydata_tv_apps_entry"
        private const val APP_DETAILS = "keydata_app_detail"
        private const val FILE_DETAILS = "keydata_file_details"
        private const val PROTOCOL = "keydata_protocol"
        private const val TV_SPLIT_CLASS = "keydata_tvsplitclass"
        private const val X_PLATFORM_TOKEN = "keydata_x_platform_token"
        private const val KEY_FCM = "keydata_fcm"
        private const val KEY_SPLIT_POS = "keydata_split_pos"
        private const val KEY_ACTIVITY = "keydata_activity"
        private const val KEY_ADBLOCK_SWITCH = "keydata_adblock"
        private const val KEY_ISLOGGEDIN = "key_isloggedin"
    }
}