package com.vpn.fastestvpnservice.viewmodels

import android.content.Context
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.vpn.fastestvpnservice.beans.Server
import com.vpn.fastestvpnservice.beans.ServerData
import com.vpn.fastestvpnservice.beans.ServerResponse
import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
import retrofit2.Call

class ServerListViewModel(context: Context): ViewModel() {

    val mutableLiveData = MutableLiveData<List<ServerData>>()
    val mutableLiveDataFavourite = MutableLiveData<List<Server>>()
    val mutableLiveDataFavUnFav = MutableLiveData<ServerResponse?>()
    private var preferencesHelper: BasePreferenceHelper

    init {
        preferencesHelper = BasePreferenceHelper(context)
    }

    fun getFavList(): ArrayList<Server> {
        var tempList = ArrayList<Server>()
        preferencesHelper.getServerData().let {
            it.forEach {
                tempList.addAll(it.servers?.filter {
                    it.isFavourited == true
                }!!)
            }
        }
        return tempList
    }

    fun updateFavServer(server: Server) {
        server.isFavourited = server.isFavourited != true
        val serverData = preferencesHelper.getServerData()

        serverData.forEach {
            it.servers?.forEachIndexed { index, obj ->
                if (server.id == obj.id) {
                    it.servers.set(index, server)

                }
            }
        }
        preferencesHelper.saveServerData(serverData as ArrayList<ServerData>)
    }

    fun filterServersByISO(serverlist: ArrayList<Server>): ArrayList<Server> {

        serverlist.forEachIndexed { index, server ->
            Log.d("serverlist_test", server.server_name + " , " + server.country)
        }

        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        serverlist.forEachIndexed { index, server ->
            Log.d("serverlist_test 2", server.server_name + " , " + server.country)
        }

        var serverprotocol = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        serverprotocol.forEachIndexed { index, server ->
            Log.d("serverlist_test p", server.server_name + " , " + server.country)
        }

        var distinctBy: List<Server>
        distinctBy = serverprotocol.distinctBy {
            it.iso
        }

        distinctBy.forEachIndexed { index, server ->
            Log.d("serverlist_test d", server.server_name + " , " + server.country)
        }

        serverprotocol.groupBy(Server::country).mapValues { entry ->

            for ((index, value) in distinctBy.withIndex()) {

                if (entry.key == value.country) {
                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }

                    var total_enables = entry.value.sumBy { it.enable }

                    println("--testing "+entry.value.size +" : "+total_enables+" : "+value.country)

                    entry.value.forEachIndexed { indexs, server ->
                        Log.d("test_country_servers",server.country + " " + server.server_name.toString())
                    }

                    distinctBy.get(index).countryServers = entry.value

                    if (total_enables >= 1) {
                        distinctBy.get(index).enableServers = 1
                    } else {
                        distinctBy.get(index).enableServers = 0
                    }
                }

            }
        }

        distinctBy.forEachIndexed { index, server ->
            Log.d("serverlist_test d 2", server.server_name + " , " + server.country + " , " + server.totalServers)
        }

        return (distinctBy as ArrayList<Server>)
    }

    fun filterServersByISOTV(serverlist: ArrayList<Server>): ArrayList<Server> {

        serverlist.forEachIndexed { index, server ->
            Log.d("serverlist test", server.server_name + " , " + server.country)
        }

        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        serverlist.forEachIndexed { index, server ->
            Log.d("serverlist 2 test 2", server.server_name + " , " + server.country)
        }

        var serverprotocol = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        serverprotocol.forEachIndexed { index, server ->
            Log.d("serverprotocol test", server.server_name + " , " + server.country)
        }

        var distinctBy: List<Server>
        distinctBy = serverprotocol.distinctBy {
            it.iso
        }

        distinctBy.forEachIndexed { index, server ->
            Log.d("distinctBy test", server.server_name + " , " + server.country)
        }

        serverprotocol.groupBy(Server::country).mapValues { entry ->

            for ((index, value) in distinctBy.withIndex()) {

                if (entry.key == value.country) {
                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }

                    var total_enables = entry.value.sumBy { it.enable }

                    println("--testing "+entry.value.size +" : "+total_enables+" : "+value.country)

                    if (total_enables >= 1) {
                        distinctBy.get(index).enableServers = 1
                    } else {
                        distinctBy.get(index).enableServers = 0
                    }
                }

            }
        }

        distinctBy.forEachIndexed { index, server ->
            Log.d("distinctBy_test_enable", server.server_name + " , " + server.enable)
        }

        val enabledServer = distinctBy.filter {
            it.enable == 1
        }

        return (enabledServer as ArrayList<Server>)
    }


    // By Khubaib...

    fun filterServersAllCategory(serverlist: ArrayList<Server>): ArrayList<Server> {
        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        val serverProtocol = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        val distinctBy: List<Server> = serverProtocol.distinctBy {
            it.server_name
        }

        val data = distinctBy as ArrayList<Server>

        data.sortBy {
            it.server_name
        }
//        serverProtocol.groupBy(Server::country).mapValues { entry ->
//            for ((index, value) in distinctBy.withIndex()) {
//                if (entry.key == value.country) {
//                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
//                }
//            }
//        }

        return (data)
    }

    fun filterServersWithTvCountries(serverlist: ArrayList<Server>): ArrayList<Server> {
        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        val serverprotocol = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        val distinctBy: List<Server> = serverprotocol.distinctBy {
            it.server_name
        }

        serverprotocol.groupBy(Server::country).mapValues { entry ->
            for ((index, value) in distinctBy.withIndex()) {
                if (entry.key == value.country) {
                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
                }
            }
        }

        val enabledServer = distinctBy.filter {
            it.enable == 1
        }

        return (enabledServer as ArrayList<Server>)
    }

    fun filterServersByStreamingServers(serverlist: ArrayList<Server>): ArrayList<Server> {

        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        var serverprotocol = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        var distinctBy: List<Server>
        distinctBy = serverprotocol.distinctBy {
            it.server_name
        }

        serverprotocol.groupBy(Server::country).mapValues { entry ->
            for ((index, value) in distinctBy.withIndex()) {
                if (entry.key == value.country) {
                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
                }
            }
        }
        return (distinctBy as ArrayList<Server>)
    }

    fun filterServersByStreamingServersTV(serverlist: ArrayList<Server>): ArrayList<Server> {

        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        var serverprotocol = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        var distinctBy: List<Server>
        distinctBy = serverprotocol.distinctBy {
            it.server_name
        }

        serverprotocol.groupBy(Server::country).mapValues { entry ->
            for ((index, value) in distinctBy.withIndex()) {
                if (entry.key == value.country) {
                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
                }
            }
        }

        val enabledServer = distinctBy.filter {
            it.enable == 1
        }

        return (enabledServer as ArrayList<Server>)
    }

    fun filterServerByConnectionCount(serverlist: ArrayList<Server>): Server {
        //sort start//
        serverlist.sortWith(Comparator { s1, s2 ->
            return@Comparator s1.country_sort.compareTo(s2.country_sort)
        })

        var temp = serverlist.filter {
            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
        }

        val distinctBy = temp.sortedBy {
            it.connection_count
        }.distinctBy {
            it.iso
        }

        distinctBy.forEachIndexed { index, server ->
            Log.d("test server cc", server.server_name.toString() + server.country)
        }

        return distinctBy[0]
    }

    fun getFilteredServerListByConnectionCount(serverList: ArrayList<Server>, serverObj: Server): Server {
        val protocol = preferencesHelper.getProtocol().title
        var tempList = ArrayList<Server>()
        var tempList2 = ArrayList<Server>()

        for (i in serverList.indices) {
            var obj = serverList[i]

            if (obj.iso == serverObj.iso && protocol.equals(obj.protocol, ignoreCase = true)) {
                tempList.add(obj)
            }
        }

        for (server in tempList)
        {
            if (serverObj.enableServers == 1)
            {
                if (server.enable == 1)
                {
                    tempList2.add(server)
                }
            }
            else{
                if (server.enable == 0){
                    tempList2.add(server)
                }
            }

        }

        tempList2.sortBy {
            it.connection_count
        }

        tempList2.forEach {
            Log.d("tempList2", it.server_name + " : " + it.connection_count)
        }

        return tempList2[0]
    }

    fun favAndUnFav(server: Server) {
        updateFavServer(server)
        WebServiceFactory.getInstance().setFavUnfav("${server.id}")
            .enqueue(RetrofitNetworkHandling<Any>(object :
                RetrofitNetworkHandling.ResponseCallback<Any> {
                override fun onSuccess(call: Call<Any>?, response: Any?) {
                    try {
                        Log.d("test_api_response","Response favAndUnFav = " + response.toString())
                        val gson = Gson()
                        val jsonString = gson.toJson(response)
                        val type = object : TypeToken<ServerResponse>() {}.type
                        val data = gson.fromJson<ServerResponse>(jsonString, type)
                        Log.d("test_api_response","favAndUnFav = " + response.toString())

                        if (data.error == 0)
                        {
                            mutableLiveDataFavUnFav.value = data
//                        UIHelper.showToast(data.message)
                        }
                        else {
                            mutableLiveDataFavUnFav.value = null
                        }
                    } catch (ex: Exception) {
                        Log.d("test_api_response","favAndUnFav catch = " + response.toString())

                    }
                }

                override fun onFail(call: Call<Any>?, response: Any?) {
                    mutableLiveDataFavUnFav.value = null
                }

                override fun onError(call: Call<Any>?, response: Any?) {
                    mutableLiveDataFavUnFav.value = null
                }

            }))

    }
}