package com.gh.gamecenter.feature.entity

import android.os.Parcelable
import android.text.TextUtils
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.common.entity.Display
import com.gh.gamecenter.common.entity.IconFloat
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.core.provider.*
import com.gh.gamecenter.feature.HaloApp
import com.gh.gamecenter.feature.R
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.provider.IRegionSettingHelperProvider
import com.google.gson.annotations.SerializedName
import com.lightgame.download.DownloadEntity
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import java.util.*

@Parcelize
data class GameEntity(
    @SerializedName("_id")
    var id: String = "",
    @SerializedName("icon")
    private var mIcon: String? = null,
    @SerializedName("ori_icon")
    private var mRawIcon: String? = null,
    @SerializedName("name")
    private var mName: String? = null, // 将 name 变成私有 mName 调用 name 时直接拼接成 mName + nameSuffix
    @SerializedName("name_suffix")
    var nameSuffix: String = "",
    @SerializedName("subtitle")
    private var mSubtitle: String = "",
    @SerializedName("subtitle_style")
    private var mSubtitleStyle: TagStyleEntity? = null,
    @SerializedName("advance_download")
    private var mAdvanceDownload: Boolean = false,
    @SerializedName("brief")
    private var mBrief: String? = null,

    @SerializedName("appointment")
    private var mReservable: Boolean = false, // 此游戏是否处于可预约状态
    @SerializedName("appointment_button")
    var reserveStatus: String = "", // 预约状态供用户预约列表使用，值存在的话，有两种值 -> appointment(已预约), download(已上线)

    // 插件标签
    private var tag: ArrayList<String>? = null,
    private var apk: ArrayList<ApkEntity>? = null,
    @SerializedName("apk_normal")
    private var apkNormal: ArrayList<ApkEntity>? = null,
    @SerializedName("apk_search")
    var apkSearch: ArrayList<ApkEntity>? = null,

    @SerializedName("apk_index")
    var apkIndex: ArrayList<ApkEntity>? = null,

    var collection: ArrayList<GameCollectionEntity> = ArrayList(),
    var slide: String? = null,
    var test: TestEntity? = null,

    @SerializedName("d_button_add_word")
    private var mDownloadAddWord: String? = null,

    var image: String? = null,
    var type: String? = null,
    var isPluggable: Boolean = false,
    var link: String? = null,
    var text: String? = "",
    @SerializedName("link_community", alternate = ["community"])
    var community: CommunityEntity? = CommunityEntity(),
    var display: Display? = null,

    @SerializedName("apk_link")
    var apkLink: ArrayList<ApkLink>? = null,

    @SerializedName("concern_article_exists")
    var isNewsExists: Boolean = true,

    @SerializedName("download_off_text")
    private var mDownloadOffText: String? = null,

    @SerializedName("download_off_status")
    private var mDownloadOffStatus: String? = null, // "off/dialog/toast", 只关闭、关闭且弹窗、关闭且toast

    @SerializedName("download_off_dialog")
    private var mDownloadOffDialog: Dialog? = null,

    @SerializedName("libao_exists")
    var isLibaoExists: Boolean = false,

    @SerializedName("server_remark")
    var serverRemark: String? = null,

    @SerializedName("server_type")
    var serverType: String? = null,

    @SerializedName("server_label")
    var serverLabel: ColorEntity? = null,

    @SerializedName("server")
    var serverEntity: ServerCalendarEntity? = null,

    @SerializedName("server_genre")
    var serverGenre: String? = null,

    @SerializedName("remaining_server")
    var serverRemaining: List<GameEntity>? = null,

    // 下载状态
    @SerializedName("download_status")
    var downloadStatus: String? = "",

    var kaifuTimeHint: Long? = null,

    var subjectData: GameSubjectData? = null,

    // 所有标签(插件标签和游戏标签)
    @SerializedName(value = "new_tag_style")
    private var mTagStyle: ArrayList<TagStyleEntity> = ArrayList(),
    var des: String? = null,
    // 用来标记在专题中的序号，仅用于曝光记录
    var sequence: Int? = -1,
    // 用来标记在外部页面中的序号，仅用于曝光记录，具体细节可见 https://git.ghzs.com/pm/halo-app-issues/-/issues/1087
    var outerSequence: Int? = -1,
    // 用来标记平台名称，仅用于曝光记录
    var platform: String? = "",

    // 用来标记下载的类型，仅用于曝光记录
    @SerializedName("download_type")
    var downloadType: String? = "",

    // 用来标记下载完成的类型，仅用于曝光记录
    @SerializedName("download_complete_type")
    var downloadCompleteType: String? = "",

    // 用于开服表标记是否为置顶项目
    @SerializedName("is_fixed_top")
    var fixedTop: Boolean? = false,
    var fixedTopHint: Boolean? = false,

    @SerializedName("download_notice")
    val downloadAd: LinkEntity? = null,

    // 关联应用，供首页替换游戏确定该游戏是否应该被替换使用
    @SerializedName("relation_game_ids")
    var relatedGameIds: ArrayList<String>? = arrayListOf(),

    @SerializedName("download_dialog")
    var downloadDialog: ArrayList<Dialog>? = arrayListOf(),

    var auth: Auth? = null,

    @SerializedName("auth_dialog")
    var authDialog: AuthDialogEntity? = null,

    @SerializedName("is_related")
    var isRelated: Boolean = false,

    @SerializedName("rating_open")
    var isRatingOpen: Boolean = false,

    @SerializedName("zone_open")
    var isZoneOpen: Boolean = false,

    @SerializedName("bbs_open")
    var isBbsOpen: Boolean = false,

    @SerializedName("show_comment")
    var showComment: Boolean = false, // 游戏评论是否打开

    // 分类，取值有 online (网络游戏) , local (单机游戏)， welfare (福利游戏)，simulator（模拟器游戏）
    @SerializedName("category")
    private var mCategory: String? = "",
    // 7天下载量
    var download: Int = 0,
    // subject -> imageSlide
    val games: List<GameEntity>? = null,

    //首页设置
    @SerializedName("home_setting")
    val homeSetting: HomeSetting = HomeSetting(),
    var linkType: String = "",
    @SerializedName("index_plugin")
    var indexPlugin: String = "open",

    // 游戏版本 （本地字段），供下载统计使用
    var gameVersion: String = "",

    // icon 角标
    @SerializedName("icon_subscript")
    var mIconSubscript: String? = null,

    @SerializedName("info")
    var info: GameInfo? = null,

    @SerializedName("permission_dialog_status")
    var permissionDialogStatus: String? = "", // 权限弹窗，off(关闭)、on(开启)，默认：off

    // 镜像数据，细节见 [RegionSettingHelper]
    @SerializedName("mirror_status")
    var mirrorStatus: String? = "",
    @SerializedName("mirror_data")
    private var mMirrorData: GameEntity? = null,
    // 镜像数据 2
    @SerializedName("mirror_status2")
    var mirrorStatus2: String? = "",
    @SerializedName("mirror_data2")
    private var mMirrorData2: GameEntity? = null,

    // 游戏评分
    @SerializedName("new_star")
    val star: Float = 10F,
    // 游戏评分数量
    @SerializedName("comment_count")
    var commentCount: Int = 0,
    // 是否支持不安装直接评论
    @SerializedName("direct_comment")
    var directComment: Boolean = false,
    // xxx人想玩
    @SerializedName("h5_link")
    private var mH5Link: LinkEntity? = null,
    val visit: Int = 0,
    @SerializedName("played_time")
    var playedTime: Long = 0,
    @SerializedName("played_game_id")
    val playedGameId: String = "",
    @SerializedName("mutex_package")
    val mutexPackage: List<String>? = null,
    @SerializedName("version_number")
    private val mVersionNumber: String = "",// 无版号无内购无弹窗、无版号无内购有弹窗、无版号有内购、有版号
    @SerializedName("plugin_link")
    val pluginLink: List<PluginLink> = arrayListOf(),
    @SerializedName("p_button_add_word")
    var pluginDesc: String = "", //插件功能描述
    var pluggableCollection: GameCollectionEntity? = null, //插件化包所在的合集
    @SerializedName("assign_remark")
    val assignRemark: AssignRemark = AssignRemark(),
    @SerializedName("zone_setting")
    var zone: ZoneEntity = ZoneEntity(),
    @SerializedName("comment_description")
    var commentDescription: String = "",
    @SerializedName("ignore_comment")
    var ignoreComment: Boolean = false,
    @SerializedName("overseas_address_dialog")
    var overseasAddressDialog: OverseasAddressDialog? = null,
    var simulator: SimulatorEntity? = null,
    @SerializedName("simulator_type")
    var simulatorType: String = "",
    @SerializedName("is_recently_played")
    var isRecentlyPlayed: Boolean = false,
    var active: Boolean = true,
    @SerializedName("package_dialog")
    val packageDialog: PackageDialogEntity? = null,
    @SerializedName("top_video")
    val topVideo: SimpleVideoEntity? = null,
    @SerializedName("column_recommend")
    val columnRecommend: LinkEntity? = null,

    @SerializedName("simulator_config_url")
    val simulatorGameConfig: String? = "",

    @SerializedName("content_tag")
    val contentTag: ContentTag? = null,

    @SerializedName("update_time")
    val updateTime: Long = 0L,

    @SerializedName("bbs_id")
    var bbsId: String = "",

    //游戏单推荐分数
    @SerializedName("recommend_star")
    var recommendStar: Int = 5,
    //游戏单推荐理由
    @SerializedName("recommend_text")
    var recommendText: String = "",

    // 专题封面图
    @SerializedName("column_image")
    var columnImage: String = "",

    // 本地字段，使用镜像信息
    var useMirrorInfo: Boolean = false,

    // 本地字段，最后打开时间
    var lastPlayedTime: Long = 0,

    // 本地字段，曝光用
    var displayContent: String = "",
    var isPlatformRecommend: Boolean = false,
    // 从启动弹窗跳转到对应游戏列表时候记录的启动弹窗数据 (ugly ugly ugly)
    var welcomeDialogId: String? = null,
    var welcomeDialogTitle: String? = null,

    @SerializedName("google_status")
    var gAppsSwitch: String? = "", // 是否需要谷歌框架，目前只用在畅玩游戏里使用

    @SerializedName("column_rank")
    var columnRank: ColumnRank? = null,//榜单详情
    @SerializedName("ad_icon_active")
    var adIconActive: Boolean = false,// 游戏广告 true显示，false隐藏。只有当type=ad时才会返回该字段
    @SerializedName("recommend_tag")
    var recommendTag: String = "",
    @SerializedName("event_type")
    var eventType: String = "",// 事件类型（test：测试、first：首发、update：更新）
    var time: TimeEntity? = null,

    @SerializedName("icon_float")
    var mIconFloat: IconFloat? = null,//图标浮层

    // 镜像字段
    @SerializedName("content_tag_status")
    val contentTagStatus: String = "off",//on（生效）/off（不生效）

    // 镜像字段
    @SerializedName("mirror_server")
    val mirrorServer: GameDetailServer? = null,

    // 专题id，用于曝光使用
    var subjectId: String? = null,
    // 专题名字，用于曝光使用
    var subjectName: String? = null,
    // 外层页面 id ，用于曝光使用
    var containerId: String? = null,
    // 外层页面类型，用于曝光使用
    var containerType: String? = null,

    // 游戏分类，用于埋点使用
    var gameType: String = "",
    //游戏存档 需要使用
    var configUrl: String = "",
    //是否广告，用于曝光使用
    var isAdData: Boolean = false,
    //游戏详情大家都在玩推荐类型：标签推荐/下载推荐/安装推荐，用于曝光使用
    var recommendType: String = ""
) : Parcelable {

    constructor(id: String?) : this() {
        this.id = id ?: "empty gameId"
    }

    constructor(id: String?, name: String?) : this() {
        this.id = id ?: "empty gameId, it's name is $name"
        this.mName = name
    }

    @IgnoredOnParcel
    private var entryMap: androidx.collection.ArrayMap<String, DownloadEntity>? =
        androidx.collection.ArrayMap()

    @IgnoredOnParcel
    var gameLocation: GameLocation? = null

    // 曝光事件，若本 gameEntity 被 itemData 包裹请将曝光事件放置于外层的 itemData
    @IgnoredOnParcel
    var exposureEvent: ExposureEvent? = null

    @IgnoredOnParcel
    var testTime: String? = "" // 开测时间

    @IgnoredOnParcel
    var briefStyle: String? = "" // 本地处理得到的简介显示配置

    @IgnoredOnParcel
    var shouldShowNameSuffix = true // 专题级开关，只要这个开关为 false，实体有 suffix 也不显示

    @IgnoredOnParcel
    private var mValidApkList: ArrayList<ApkEntity>? = null // 有效的 apk 列表，避免重复调用

    @IgnoredOnParcel
    private var mLastMirrorUpdatedTime: Long = 0 // 上一次检查镜像的时间

    @IgnoredOnParcel
    private var mIsVGame: Boolean = false

    @IgnoredOnParcel
    var name: String?
        get() = if (shouldUseMirrorInfo()) {
            obtainMirrorData()?.mName?.removeSuffix(".") + if (shouldShowNameSuffix) obtainMirrorData()?.nameSuffix
                ?: "" else ""
        } else {
            mName?.removeSuffix(".") + if (shouldShowNameSuffix) nameSuffix else ""
        }
        set(value) {
            mName = value
        }

    /**
     * 获取镜像数据
     */
    fun obtainMirrorData(): GameEntity? {
        val regionSettingProvider = ARouter.getInstance()
            .build(RouteConsts.provider.regionSettingHelper)
            .navigation() as? IRegionSettingHelperProvider

        return when (regionSettingProvider?.getMirrorPosition(id)) {
            1 -> mMirrorData
            2 -> mMirrorData2
            else -> null
        }
    }

    @IgnoredOnParcel
    var h5Link: LinkEntity?
        get() = if (shouldUseMirrorInfo()) {
            obtainMirrorData()?.mH5Link
        } else mH5Link
        set(value) {
            mH5Link = value
        }

    @IgnoredOnParcel
    var downloadOffStatus: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mDownloadOffStatus else mDownloadOffStatus
        set(value) {
            mDownloadOffStatus = value
        }

    @IgnoredOnParcel
    var downloadOffDialog: Dialog?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mDownloadOffDialog else mDownloadOffDialog
        set(value) {
            mDownloadOffDialog = value
        }

    @IgnoredOnParcel
    val nameWithoutSuffix: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mName?.removeSuffix(".") else mName?.removeSuffix(
            "."
        )

    @IgnoredOnParcel
    var isReservable: Boolean
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mReservable ?: false else mReservable
        set(value) {
            mReservable = value
        }

    @IgnoredOnParcel
    var icon: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mIcon else mIcon
        set(value) {
            mIcon = value
        }

    @IgnoredOnParcel
    var rawIcon: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mRawIcon else mRawIcon
        set(value) {
            mRawIcon = value
        }

    @IgnoredOnParcel
    var iconSubscript: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mIconSubscript else mIconSubscript
        set(value) {
            mIconSubscript = value
        }

    @IgnoredOnParcel
    var iconFloat: IconFloat?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mIconFloat else mIconFloat
        set(value) {
            mIconFloat = value
        }

    @IgnoredOnParcel
    var category: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mCategory else mCategory
        set(value) {
            mCategory = value
        }

    @IgnoredOnParcel
    val categoryChinese: String
        get() = when (category) {
            "online" -> "网络"
            "local" -> "单机"
            "welfare" -> "福利"
            "simulator" -> "模拟器"
            else -> category ?: ""
        }

    @IgnoredOnParcel
    var brief: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mBrief else mBrief
        set(value) {
            mBrief = value
        }

    @IgnoredOnParcel
    var subtitle: String
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mSubtitle ?: "" else mSubtitle
        set(value) {
            mSubtitle = value
        }

    @IgnoredOnParcel
    var subtitleStyle: TagStyleEntity?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mSubtitleStyle else mSubtitleStyle
        set(value) {
            mSubtitleStyle = value
        }

    @IgnoredOnParcel
    var advanceDownload: Boolean
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mAdvanceDownload ?: false else mAdvanceDownload
        set(value) {
            mAdvanceDownload = value
        }

    @IgnoredOnParcel
    var hideSizeInsideDes: Boolean = false

    @IgnoredOnParcel
    val decoratedDes: String?
        get() = if (
            getApk().size > 0
            && !hideSizeInsideDes
            && ((TextUtils.isEmpty(subjectData?.briefStyle)
                    || subjectData?.briefStyle?.contains("size") == true)
                    || subjectData?.briefStyle?.contains("recommend") == true)
        ) {
            getApk().firstOrNull()?.size + "  " + brief
        } else {
            brief
        }

    @IgnoredOnParcel
    val downloadOffText: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mDownloadOffText else mDownloadOffText

    @IgnoredOnParcel
    var tagStyle: ArrayList<TagStyleEntity>
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mTagStyle?.apply {
            removeAll {
                it.name.toLowerCase(
                    Locale.getDefault()
                ) == "mod版"
            }
        }
            ?: arrayListOf() else mTagStyle
        set(value) {
            mTagStyle = value
        }

    @IgnoredOnParcel
    val downloadAddWord: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mDownloadAddWord else mDownloadAddWord

    @IgnoredOnParcel
    val versionNumber: String?
        get() = if (shouldUseMirrorInfo()) obtainMirrorData()?.mVersionNumber else mVersionNumber

    @IgnoredOnParcel
    val downloadStatusChinese: String
        get() = when (downloadStatus) {
            "on" -> "开启"
            "smooth" -> "畅玩"
            "appointment" -> "预约"
            "demo" -> "试玩"
            else -> ""
        }

    //是否需要弹出试玩弹窗
    fun isShowVersionNumber(): Boolean {
        return versionNumber == "无版号无内购有弹窗"
    }

    //是获取试玩弹窗提示文案
    fun getVersionNumberString(): String {
        return when (versionNumber) {
            "无版号有内购" -> HaloApp.getInstance().getString(R.string.attempt_tips_1)
            "无版号无内购有弹窗" -> HaloApp.getInstance().getString(R.string.attempt_tips_2)
            else -> ""
        }
    }

    fun setWelcomeDialogInfoIfAvailable() {
        val appProvider = ARouter.getInstance().build(RouteConsts.provider.app).navigation() as? IAppProvider
        welcomeDialogId = appProvider?.get(Constants.WELCOME_DIALOG_ID, false) as? String
        welcomeDialogTitle = appProvider?.get(Constants.WELCOME_DIALOG_LINK_TITLE, false) as? String
    }

    fun getTag(): ArrayList<String> {
        if (tag == null) tag = ArrayList()
        val configProvider = ARouter.getInstance().build(RouteConsts.provider.config).navigation() as? IConfigProvider
        if (configProvider?.isShowPlugin(id) == false) return ArrayList()
        return tag!!
    }

    fun setTag(tag: ArrayList<String>?) {
        this.tag = tag
    }

    fun getApk(): ArrayList<ApkEntity> {
        if (mValidApkList == null || shouldApkReCheckMirrorInfo()) {
            if (shouldUseMirrorInfo()) return obtainMirrorData()?.getApk() ?: arrayListOf()

            var rawApk = apk ?: ArrayList()
            val configProvider =
                ARouter.getInstance().build(RouteConsts.provider.config).navigation() as? IConfigProvider
            if (configProvider?.isShowPlugin(id) == false) {
                rawApk = getApkNormal()
            } else if (gameLocation == GameLocation.INDEX && apkIndex != null) {
                rawApk = apkIndex!!
            } else if (gameLocation == GameLocation.SEARCH && apkSearch != null) {
                rawApk = apkSearch!!
            }

            if (isVGame()) {
                val vHelperProvider =
                    ARouter.getInstance().build(RouteConsts.provider.vhelper).navigation() as? IVHelperProvider
                rawApk.forEach {
                    it.setPlatform(vHelperProvider?.getPlatformV() ?: "")
                    it.url = vHelperProvider?.getVUrl(it.url)
                }
            }

            mValidApkList = rawApk

            mLastMirrorUpdatedTime = System.currentTimeMillis()
        }

        return mValidApkList!!
    }

    /**
     * 获取唯一的包名，仅单版本游戏有效，多版本的游戏请不要调用
     */
    fun getUniquePackageName(): String? {
        return getApk().firstOrNull()?.packageName
    }

    fun getOriginalApk(): ArrayList<ApkEntity> {
        if (apk == null) apk = ArrayList()
        return apk!!
    }

    fun setApk(apk: ArrayList<ApkEntity>?) {
        this.apk = apk
    }

    fun getApkNormal(): ArrayList<ApkEntity> {
        if (apkNormal == null) {
            apkNormal = ArrayList()
        }
        return apkNormal!!
    }

    fun setApkNormal(apkNormal: ArrayList<ApkEntity>?) {
        this.apkNormal = apkNormal
    }

    /**
     * 丢弃 apk 以外的 apkNormal、apkIndex、apkSearch、apkLink
     */
    fun dropOtherApk() {
        apkNormal = arrayListOf()
        apkIndex = arrayListOf()
        apkSearch = arrayListOf()
        apkLink = arrayListOf()
        mValidApkList = null
    }

    fun getEntryMap(): androidx.collection.ArrayMap<String, DownloadEntity> {
        return entryMap!!
    }

    fun getRawIconInAdvanced(): String {
        return rawIcon ?: icon ?: ""
    }

    fun setEntryMap(entryMap: androidx.collection.ArrayMap<String, DownloadEntity>?) {
        if (entryMap != null) {
            this.entryMap = entryMap
        }
    }

    fun getGameCategory(): GameCategory {
        return when {
            isWelfareGame() -> GameCategory.WELFARE_GAME
            isOnlineGame() -> GameCategory.ONLINE_GAME
            isLocalGame() -> GameCategory.LOCAL_GAME
            isInternationalLocalGame() -> GameCategory.INTERNATIONAL_LOCAL_GAME
            isInternationalOnlineGame() -> GameCategory.INTERNATIONAL_ONLINE_GAME
            else -> GameCategory.LOCAL_GAME
        }
    }

    fun setIsPlatformRecommend(isPlatformRecommend: Boolean) {
        this.isPlatformRecommend = isPlatformRecommend
    }

    /**
     * 游戏所属类型
     * 网络游戏：category 为 online 的游戏
     * 单机游戏：category 为 local 的游戏
     * 福利游戏：category 为 welfare 的游戏
     */
    private fun isOnlineGame(): Boolean {
        return category.equals("online")
    }

    private fun isLocalGame(): Boolean {
        return category.equals("local")
    }

    private fun isWelfareGame(): Boolean {
        return category.equals("welfare")
    }

    private fun isInternationalLocalGame(): Boolean {
        return category.equals("gjlocal")
    }

    private fun isInternationalOnlineGame(): Boolean {
        return category.equals("gjonline")
    }

    /**
     * 是否需要重新检查镜像中的 apk 信息
     * 当 useMirrorInfo 的值为 true 时，就不重新检查了，维持镜像的打开状态
     * 仅当 useMirrorInfo 的值为 false 时，为了避免一直卡在镜像的关闭状态，才去重新检查
     */
    private fun shouldApkReCheckMirrorInfo(): Boolean {
        if (!useMirrorInfo
            && System.currentTimeMillis() - mLastMirrorUpdatedTime > CHECK_MIRROR_INFO_INTERVAL
        ) {
            return true
        }

        return false
    }

    fun shouldUseMirrorInfo(): Boolean {
        if (useMirrorInfo) {
            return true
        } else {
            val provider = ARouter.getInstance().build(RouteConsts.provider.regionSettingHelper)
                .navigation() as? IRegionSettingHelperProvider
            useMirrorInfo =
                (mirrorStatus == "on" || mirrorStatus2 == "on") && provider?.shouldThisGameDisplayMirrorInfo(id) == true
        }

        return useMirrorInfo
    }

    /**
     * 获取镜像的序号
     * @return -1 代表没有使用镜像， 1 代表使用镜像 1，2 代表使用镜像 2
     */
    fun getMirrorPosition(): Int {
        val provider = ARouter.getInstance().build(RouteConsts.provider.regionSettingHelper)
            .navigation() as? IRegionSettingHelperProvider

        return provider?.getMirrorPosition(id) ?: -1
    }

    /**
     * 是否是畅玩游戏 （当且仅当畅玩开关打开，且游戏类型为畅玩才会返回 true）
     */
    fun isVGame(): Boolean {
        if (!mIsVGame) {
            val vHelperProvider =
                ARouter.getInstance().build(RouteConsts.provider.vhelper).navigation() as? IVHelperProvider
            mIsVGame = if (vHelperProvider?.isVGameOn() == false) {
                false
            } else {
                downloadStatus == "smooth"
            }
        }

        return mIsVGame
    }

    fun isUseDefaultServerStyle(): Boolean {
        return if (serverLabel == null) {
            false
        } else {
            serverLabel?.value == "公测"
                    || serverLabel?.value == "不删档内测"
                    || serverLabel?.value == "删档内测"
                    || serverLabel?.value == "即将开测"
                    || serverLabel?.value == "明日开测"
        }
    }

    fun isSpecialDownload(): Boolean {
        val provider = ARouter.getInstance().build(RouteConsts.provider.regionSettingHelper)
            .navigation() as? IRegionSettingHelperProvider
        return provider?.shouldThisGameShowSpecialDownload(id) == true
    }

    /**
     * 设置镜像数据
     * @param position 镜像1 or 镜像2
     */
    fun setMirrorData(position: Int, mirrorData: GameEntity?) {
        if (position == 1) {
            mMirrorData = mirrorData
        } else if (position == 2) {
            mMirrorData2 = mirrorData
        }
    }

    fun getTypeName() =
        when (type) {
            "filter" -> "算法过滤"
            "recommend" -> "专题推荐"
            "ad" -> "游戏广告"
            else -> ""
        }

    fun toSimpleGame(): SimpleGame {
        val simpleGame = SimpleGame()
        simpleGame.id = id
        simpleGame.mName = mName
        simpleGame.nameSuffix = nameSuffix
        simpleGame.mIcon = mIcon
        simpleGame.mRawIcon = mRawIcon
        simpleGame.active = active
        simpleGame.iconSubscript = iconSubscript
        simpleGame.recommendStar = recommendStar
        simpleGame.recommendText = recommendText
        return simpleGame
    }

    fun convertSimulatorGameRecordEntity(): SimulatorGameRecordEntity {
        val entity = SimulatorGameRecordEntity()
        entity.id = id
        entity.brief = brief
        entity.des = des
        entity.icon = rawIcon
        entity.iconSubscript = iconSubscript
        entity.name = name
        entity.tagStyle = tagStyle
        entity.isLibaoExist = isLibaoExists
        entity.tag = tag
        entity.simulatorType = simulatorType
        entity.simulator = simulator
        entity.category = category ?: ""
        entity.isRecentlyPlayed = isRecentlyPlayed
        entity.apk = getApk()
        entity.apkNormal = getApkNormal()
        return entity
    }

    companion object {
        const val TAG: String = "GameEntity"
        const val CHECK_MIRROR_INFO_INTERVAL = 10 * 1000 // 检查镜像更新间隔 10s
    }

    @Parcelize
    class Dialog(
        var title: String = "",
        var content: String = "",
        var sites: List<Site> = listOf(),
        @SerializedName("close_button_text")
        var closeButtonText: String = "",
        @SerializedName("confirm_button")
        var confirmButton: LinkEntity = LinkEntity(),
        var rule: Rule = Rule(),
        // 值可能是 ONCE_A_DAY / EVERY_TIME_OPEN
        var alert: String = ""
    ) : Parcelable {
        @Parcelize
        class Rule(
            @SerializedName("package")
            var packageName: String = "",
            var models: ArrayList<String> = arrayListOf(),
            @SerializedName("system_versions")
            var systemVersions: ArrayList<String> = arrayListOf(),
            @SerializedName("notice_versions")
            var noticeVersions: ArrayList<String> = arrayListOf()
        ) : Parcelable

        @Parcelize
        class Site(
            var url: String = "",
            var text: String = ""
        ) : Parcelable
    }

    @Parcelize
    class PluginLink(
        @SerializedName("link_id")
        var linkId: String = "",
        var title: String = "",
        @SerializedName("link_type")
        var linkType: String = "", // article,Q&A,dialog
        @SerializedName("link_text")
        var linkText: String = "",
        var content: String = "",
        @SerializedName("link_community")
        var community: CommunityEntity? = CommunityEntity(),
        var display: Display? = null
    ) : Parcelable {

        fun getLinkEntity(): LinkEntity {
            return LinkEntity(
                link = linkId,
                title = title,
                type = linkType,
                text = linkText,
                community = community,
                display = display
            )
        }
    }

    @Parcelize
    class OverseasAddressDialog(var status: String? = "", var link: String? = "") :
        Parcelable {
        fun isEnable(): Boolean {
            return status == "show" || status == "show&download"
        }
    }

    // 游戏位置， 根据游戏位置只显示某个单独的APK
    enum class GameLocation {
        INDEX,
        SEARCH,
    }

    enum class GameCategory(val value: String) {
        ONLINE_GAME("online_game"),
        LOCAL_GAME("local_game"),
        WELFARE_GAME("welfare_game"),
        INTERNATIONAL_LOCAL_GAME("gjlocal_game"),
        INTERNATIONAL_ONLINE_GAME("gjonline_game");

        override fun toString() = value
    }

    @Parcelize
    class AssignRemark(
        @SerializedName("first_line")
        val firstLine: String = "",
        @SerializedName("second_line")
        val secondLine: String = "",
        @SerializedName("marked_red")
        val markedRed: Boolean = false,
        val recommend: Boolean = false,
        @SerializedName("start_time")
        val startTime: Long = 0,
        @SerializedName("end_time")
        val endTime: Long = 0
    ) : Parcelable

    @Parcelize
    class Auth(
        val switch: String? = null, // 开关
        @SerializedName("time_start")
        val timeStart: String? = "", // 开始时间
        @SerializedName("time_end")
        val timeEnd: String? = "" // 结束时间
    ) : Parcelable

    @Parcelize
    data class ContentTag(
        val custom: List<CustomTag> = listOf(),
        @SerializedName("zone_setting")
        val zone: ZoneEntity = ZoneEntity(),
        @SerializedName("ling_libao_exists")
        val isLibaoExists: Boolean = false,
        val server: Boolean = false,
        @SerializedName("bbs_exists")
        val isBbsExists: Boolean = false
    ) : Parcelable

    @Parcelize
    class CustomTag(
        @SerializedName("_id")
        val id: String = "",
        val text: String = "",
        val link: LinkEntity = LinkEntity(),
        val icon: Icon = Icon()
    ) : Parcelable {

        @Parcelize
        class Icon(
            @SerializedName("_id")
            var id: String = "",
            var name: String = "",
            var url: String = ""
        ) : Parcelable
    }

    @Parcelize
    class ColumnRank(
        val name: String = "",
        val position: Int = 0
    ) : Parcelable
}

@Parcelize
class SimpleGame(
    @SerializedName("_id")
    var id: String? = null,
    @SerializedName("name")
    var mName: String? = "",
    @SerializedName("name_suffix")
    var nameSuffix: String? = null,
    @SerializedName("icon")
    var mIcon: String? = null,
    @SerializedName("ori_icon")
    var mRawIcon: String? = null,
    @SerializedName("icon_subscript")
    var iconSubscript: String? = null,
    var active: Boolean = false,
    //游戏单推荐分数
    @SerializedName("recommend_star")
    var recommendStar: Int = 5,
    @SerializedName("mirror_status")
    var mirrorStatus: String? = "",
    @SerializedName("mirror_data")
    var mirrorData: SimpleGame? = null,
    @SerializedName("mirror_status2")
    var mirrorStatus2: String? = "",
    @SerializedName("mirror_data2")
    var mirrorData2: SimpleGame? = null,
    //游戏单推荐理由
    @SerializedName("recommend_text")
    var recommendText: String = "",
    @SerializedName("download_status")
    var downloadStatus: String = "",

    var subtitle: String? = "",
    @SerializedName("subtitle_style")
    var subtitleStyle: TagStyleEntity? = null,
    @SerializedName("advance_download")
    var advanceDownload: Boolean = false,
    @SerializedName("icon_float")
    var iconFloat: IconFloat? = null
) : Parcelable {

    @IgnoredOnParcel
    val name: String?
        get() = mName?.removeSuffix(".") + (nameSuffix ?: "")

    fun getIcon(): String {
        return mRawIcon ?: mIcon ?: ""
    }

    fun getDefaultIcon(): String {
        return mIcon ?: ""
    }

    fun toGameEntity(): GameEntity {
        val gameEntity = GameEntity(id = id, name = name)
        gameEntity.nameSuffix = nameSuffix ?: ""
        gameEntity.icon = mIcon
        gameEntity.rawIcon = mRawIcon
        gameEntity.iconSubscript = iconSubscript
        gameEntity.mirrorStatus = mirrorStatus
        gameEntity.mirrorStatus2 = mirrorStatus2
        gameEntity.setMirrorData(1, mirrorData?.toGameEntity())
        gameEntity.setMirrorData(2, mirrorData2?.toGameEntity())
        gameEntity.recommendStar = recommendStar
        gameEntity.recommendText = recommendText
        gameEntity.downloadStatus = downloadStatus
        gameEntity.subtitle = subtitle ?: ""
        gameEntity.subtitleStyle = subtitleStyle
        gameEntity.advanceDownload = advanceDownload
        gameEntity.iconFloat = iconFloat
        return gameEntity
    }

    fun toCommunityGameEntity(): CommunityEntity.CommunityGameEntity {
        val gameEntity = CommunityEntity.CommunityGameEntity(id = id, mName = name)
        gameEntity.nameSuffix = nameSuffix ?: ""
        gameEntity.mIcon = mIcon
        gameEntity.mRawIcon = mRawIcon
        gameEntity.iconSubscript = iconSubscript
        gameEntity.iconFloat = iconFloat
        return gameEntity
    }
}
