package com.gh.gamecenter.servers

import android.annotation.SuppressLint
import android.app.Application
import android.util.SparseIntArray
import androidx.collection.ArrayMap
import androidx.collection.arrayMapOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.filter.RegionSettingHelper
import com.gh.gamecenter.common.entity.ExposureEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.entity.ServerTestEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.schedulers.Schedulers
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.abs

class GameServersTestViewModel(application: Application, private val mColumnId: String) :
    AndroidViewModel(application) {

    private var mServerTestEntity: ServerTestEntity? = null
    private var mTimePositionSparseArray = SparseIntArray()

    val locationMap: ArrayMap<String, ArrayList<Int>> = arrayMapOf()

    private var mCurrentTimeFilter = ""
    private var mCurrentTypeFilter = ""

    var testTitle = ""
    var testRemark = ""

    // dayList 的排序很重要，改前要小心
    var dayList = arrayListOf("过去7天", "昨天", "今天", "明天", "后续")
    var typeList = arrayListOf(ALL, OPEN_TEST, UNLIMITED_TEST, LIMITED_TEST)

    val listLiveData = MutableLiveData<ArrayList<ItemData>>()
    val loadStatusLiveData = MutableLiveData<Boolean>()

    val isTestOnLiveData = MutableLiveData<Boolean>()

    @SuppressLint("CheckResult")
    fun load(filter: String = ALL) {
        mCurrentTypeFilter = filter
        RetrofitManager.getInstance().api.getGameTestServers(mColumnId, null)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ServerTestEntity>() {
                override fun onSuccess(data: ServerTestEntity) {
                    testRemark = data.remark
                    mServerTestEntity = data
                    dayList[0] = "过去${data.settings.testTimeRange}天"
                    transformData(data, filter)
                    loadStatusLiveData.postValue(true)
                    isTestOnLiveData.postValue(true)
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    loadStatusLiveData.postValue(false)
                    isTestOnLiveData.postValue(false)
                }
            })
    }

    fun updateTypeFilter(filter: String) {
        if (mServerTestEntity != null) {
            transformData(mServerTestEntity!!, filter)
        } else {
            load(filter)
        }
        mCurrentTypeFilter = filter
    }

    fun updateTimeFilter(filter: String) {
        mCurrentTimeFilter = filter
    }

    fun getTestEntity(): ServerTestEntity? {
        return mServerTestEntity
    }

    fun getCurrentTypeFilter(): String {
        return mCurrentTypeFilter
    }

    fun getCurrentTimeFilter(): String {
        return if (mCurrentTimeFilter.isEmpty()) dayList.first() else mCurrentTimeFilter
    }

    fun getDayPositionByDayString(day: String): Int {
        for ((index, dayString) in dayList.withIndex()) {
            if (dayString == day) {
                when (index) {
                    0 -> return mTimePositionSparseArray.get(Day.PAST_DAY.value)
                    1 -> return mTimePositionSparseArray.get(Day.YESTERDAY.value)
                    2 -> return mTimePositionSparseArray.get(Day.TODAY.value)
                    3 -> return mTimePositionSparseArray.get(Day.TOMORROW.value)
                    4 -> return mTimePositionSparseArray.get(Day.UPCOMING_DAY.value)
                }
            }
        }
        return -1
    }

    fun getDayRangeByPosition(position: Int): String {
        return when (listLiveData.value?.safelyGetInRelease(position)?.readableDaysOffset) {
            Day.PAST_DAY.value -> return dayList[0]
            Day.YESTERDAY.value -> return dayList[1]
            Day.TODAY.value -> return dayList[2]
            Day.TOMORROW.value -> return dayList[3]
            Day.UPCOMING_DAY.value -> return dayList[4]
            else -> ""
        }
    }

    fun getDayTextByPosition(position: Int): String {
        var dayText = ""
        val dataList = listLiveData.value

        dataList?.let {
            for ((index, value) in dataList.withIndex()) {
                if (value.time != null) {
                    dayText = value.time ?: ""
                }
                if (index == position) {
                    return dayText
                }
            }
        }
        return dayText
    }

    fun getItemAtPosition(position: Int): ItemData? {
        return listLiveData.value?.safelyGetInRelease(position)
    }

    private fun initLocationMap(itemList: ArrayList<ItemData>) {
        locationMap.clear()

        var list: ArrayList<Int>?
        var i = 0
        val size: Int = itemList.size
        while (i < size) {
            itemList[i].game?.let { gameEntity ->
                if (gameEntity.getApk().size != 0) {
                    for (apk in gameEntity.getApk()) {
                        list = locationMap[apk.packageName]
                        if (list == null) {
                            list = ArrayList()
                            locationMap[apk.packageName] = list
                        }
                        list?.add(i)
                    }
                }
            }
            i++
        }
    }

    private fun transformData(serverTestEntity: ServerTestEntity, filter: String) {
        val list = arrayListOf<ItemData>()
        val subList = arrayListOf<ItemData>()

        mTimePositionSparseArray.clear()

        var isEmptyIndeed = true // 列表是否不含有任何一个游戏，这时隐藏所有
        for (slice in serverTestEntity.sliceData) {
            subList.clear()

            val daysOffset = TimeUtils.getDaysOffset(slice.testTime)
            var testTimeInHumanReadableFormat: String

            if (daysOffset in -1..1) {
                testTimeInHumanReadableFormat = when (daysOffset) {
                    -1 -> "昨天"
                    0 -> "今天"
                    else -> "明天"
                }
                val sdf = SimpleDateFormat("(EEEE)", Locale.CHINA)
                testTimeInHumanReadableFormat = testTimeInHumanReadableFormat + " " + sdf.format(slice.testTime * 1000)
            } else {
                val sdf = SimpleDateFormat("yyyy-MM-dd (EEEE)", Locale.CHINA)
                testTimeInHumanReadableFormat = sdf.format(slice.testTime * 1000)
            }

            val readableDaysOffset = when {
                daysOffset < Day.YESTERDAY.value -> Day.PAST_DAY.value
                daysOffset > Day.TOMORROW.value -> Day.UPCOMING_DAY.value
                else -> daysOffset
            }

            subList.add(ItemData(time = testTimeInHumanReadableFormat, readableDaysOffset = readableDaysOffset))

            slice.gameList = RegionSettingHelper.filterGame(slice.gameList)
            for ((index, game) in slice.gameList.withIndex()) {
                game.serverType = game.test?.type ?: game.serverType
                if (filter == ALL || game.serverType == filter) {
                    ApkActiveUtils.filterHideApk(game) // 过滤隐藏apk

                    game.briefStyle = game.test?.gameInfo

                    if (!game.showComment) {
                        // 关闭评分不显示评分
                        game.commentCount = 0
                    }

                    game.sequence = index
                    game.testTime = testTimeInHumanReadableFormat
                    game.containerId = mColumnId
                    game.containerType = ExposureEntity.TEST_SERVER_ID
                    subList.add(
                        ItemData(
                            game = game,
                            readableDaysOffset = readableDaysOffset,
                            isTheLastOfTheLatestConsecutiveGame = index == slice.gameList.lastIndex
                        )
                    )

                    isEmptyIndeed = false
                }
            }

            // 过滤除昨天今天明天以外没有游戏的子列表
            if (subList.size > 1 || abs(daysOffset) <= 1) {
                val isCurrentDaysOffsetExist = mTimePositionSparseArray.get(readableDaysOffset, 999) != 999
                if (!isCurrentDaysOffsetExist) {
                    mTimePositionSparseArray.put(readableDaysOffset, list.size)
                }

                list.addAll(subList)

                if (subList.size == 1) {
                    list.add(ItemData(text = "暂无开测游戏", readableDaysOffset = daysOffset))
                }
            }
        }

        if (isEmptyIndeed) {
            // 没有游戏的列表不显示日期
            list.clear()
        }

        initLocationMap(list)

        listLiveData.postValue(list)
    }

    companion object {
        const val ALL = "全部"
        const val OPEN_TEST = "公测"
        const val UNLIMITED_TEST = "不删档内测"
        const val LIMITED_TEST = "删档内测"
    }

    enum class Day(val value: Int) {
        PAST_DAY(-2),
        YESTERDAY(-1),
        TODAY(0),
        TOMORROW(1),
        UPCOMING_DAY(2)
    }

    class ItemData(
        var time: String? = null,
        var game: GameEntity? = null,
        var text: String? = null,
        var readableDaysOffset: Int = 0,
        var isTheLastOfTheLatestConsecutiveGame: Boolean = false
    )

    class Factory(private val mApplication: Application, private val mColumnId: String) :
        ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return GameServersTestViewModel(mApplication, mColumnId) as T
        }
    }

}