package com.gh.gamecenter.common.utils

import androidx.collection.arrayMapOf
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.BuildConfig
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IAppProvider
import java.util.regex.Pattern
import kotlin.math.ceil

object TimestampUtils {

    private const val BASE = 1426608000000L // 基准时间
    private const val GAME_CD = 5 * 60 * 1000 // 游戏cd间隔
    private const val NEWS_CD = 10 * 60 * 1000 // 新闻cd间隔
    private const val ADDONS_CD = 10 * 60 * 1000 // 我的光环功能分组cd间隔
    private const val PACKAGES_CD = 60 * 1000 // 已收录包名更新cd间隔

    private val mIntervalMap by lazy { getIntervalMap() } // 间隔Map，保存接口及对应间隔
    private val mCDMap by lazy { getCDMap() } // CDMap，保存接口及对应CD
    private val mWhiteList by lazy { getWhiteList() } // 白名单，保存不需要添加时间戳的接口
    private val mImmediateList by lazy { getImmediateList() } // 即时名单，保存需要添加当前时间戳的接口

    /**
     * 初始化间隔Map并返回
     */
    private fun getIntervalMap() =
        arrayMapOf(
            ".*index.*" to 5,
            ".*columns.*" to 10,
            ".*games.*" to 15,
            ".*articles.*" to 20,
            ".*halo_addons.*" to 10,
            ".*packages.*" to 1
        )

    /**
     * 初始化CDMap并返回
     */
    private fun getCDMap() =
        arrayMapOf(
            ".*index.*" to GAME_CD,
            ".*columns.*" to GAME_CD,
            ".*games.*" to GAME_CD,
            ".*articles.*" to NEWS_CD,
            ".*halo_addons.*" to ADDONS_CD,
            ".*packages.*" to PACKAGES_CD
        )

    /**
     * 初始化白名单并返回
     */
    private fun getWhiteList() =
        listOf(
            ".*tasks:check.*",
            ".*novice_tasks.*",
            ".*daily_tasks.*",
            ".*fixed_tasks.*",
            ".*energies.*"
        )

    /**
     * 初始化即时名单并返回
     */
    private fun getImmediateList() = listOf(".*rating.*")

    /**
     * 判断url是否需要添加时间戳，需要则添加
     */
    @JvmStatic
    fun addTimestamp(url: String): String {
        for (key in mWhiteList) {
            if (Pattern.matches(key, url)) {
                return url
            }
        }

        val appProvider =
            ARouter.getInstance().build(RouteConsts.provider.app).navigation() as IAppProvider

        if (url.isBlank()) return url

        // 测试环境直接添加时间戳
        if (BuildConfig.DEBUG || "GH_REFRESH" == appProvider.getChannel()) {
            return when {
                url.contains("?") -> "$url&timestamp=${System.currentTimeMillis()}"
                else -> "$url?timestamp=${System.currentTimeMillis()}"
            }
        } else {
            // 即时名单直接添加时间戳
            for (key in mImmediateList) {
                if (Pattern.matches(key, url)) {
                    return when {
                        url.contains("?") -> "$url&timestamp=${System.currentTimeMillis()}"
                        else -> "$url?timestamp=${System.currentTimeMillis()}"
                    }
                }
            }

            // 检测接口是否匹配CDMap，匹配到则根据CD获取添加时间戳，否则不添加时间戳
            var cd = 0
            for (key in mCDMap.keys) {
                if (Pattern.matches(key, url)) {
                    cd = mCDMap[key]!!
                    break
                }
            }
            return when {
                cd == 0 -> url
                url.contains("?") -> "${url}&timestamp=${getTimestamp(url, cd)}"
                else -> "${url}?timestamp=${getTimestamp(url, cd)}"
            }
        }
    }

    /**
     * 根据CD获取时间戳
     */
    private fun getTimestamp(url: String, cd: Int): Long {
        var base = BASE
        for (key in mIntervalMap.keys) {
            if (Pattern.matches(key, url)) {
                base += mIntervalMap[key]!!.toLong()
                break
            }
        }
        val now = System.currentTimeMillis()
        return (ceil(((now - base).toFloat() / cd).toDouble()) * cd + base).toLong()
    }

    /**
     * 移除url中的时间戳
     */
    @JvmStatic
    fun removeTimestamp(url: String): String {
        var index = url.lastIndexOf("timestamp")
        val params = url.substring(index)
        // 连接符
        val connector = url.substring(index - 1, index)
        var key = url.substring(0, index - 1)
        index = params.indexOf("&")
        if (index != -1) {
            key = key + connector + params.substring(index + 1)
        }
        return key
    }
}