package com.gh.gamecenter.home.custom.model

import android.annotation.SuppressLint
import android.graphics.Paint
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.GameSubstituteRepositoryHelper
import com.gh.common.util.HomePluggableHelper
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.entity.PKEntity
import com.gh.gamecenter.common.livedata.NonStickyMutableLiveData
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.TextHelper
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.sp2px
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.dsp.data.GameSubjectDSPRemoteDataSource
import com.gh.gamecenter.entity.DiscoveryCardEntity
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.PullDownPush
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_BANNER
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_BANNER
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_VERTICAL_CARD
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_NOTIFICATION_COLUMN
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_RECOMMEND_CARD
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_VERTICAL_IMAGE_TEXT
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_CAROUSEL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_RANKING_LIST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_REFRESH_ICONS_4_2
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_REFRESH_SLIDE_LIST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_X_SLIDE_CARD
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_X_SLIDE_CARD_SMALL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_GAME_SUBJECT_TYPE_DOUBLE_CARD
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_GAME_SUBJECT_TYPE_GAME_VERTICAL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_GAME_SUBJECT_TYPE_GAME_VIDEO_HORIZONTAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GALLERY
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GALLERY_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_FOLD_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_TIMELINE_HORIZONTAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_ACCELERATOR_RECENTLY_PLAYED
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_COLUMN
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_DSP_GAME_COLUMN
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_GAME
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_HALO_RECOMMEND
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_PK
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMListRepository
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMListUseCase
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMRemoteDataSource
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.wrapper.MainWrapperRepository
import com.gh.vspace.VHelper
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import java.util.regex.Pattern

class CustomPageRepository private constructor(
    private val remoteDataSource: CustomPageRemoteDataSource,
    private val localDataSource: CustomPageLocalDataSource,
    private val wGameSubjectCPMRemoteDataSource: WGameSubjectCPMRemoteDataSource,
) {

    private val pageInfo = PageInfo()

    private val compositeDisposable = CompositeDisposable()

    private val shareRepository = CustomPageShareRepository.instance

    private val wGameSubjectCPMListUseCase = WGameSubjectCPMListUseCase(
        WGameSubjectCPMListRepository(wGameSubjectCPMRemoteDataSource)
    )

    private val dspSubjectUseCase = GameSubjectDSPRemoteDataSource(RetrofitManager.getInstance().dspApiService)

    private var recentItem: CustomRecentGamesItem? = null

    private var recentQQItem: CustomRecentQqMiniGamesItem? = null

    private var recentWechatItem: CustomRecentWeChatMiniGamesItem? = null

    private var pluginItem: CustomPluginItem? = null

    private var discoverCardItem: CustomDiscoverCardItem? = null

    private var recentAcceleratorItem: CustomRecentAcceleratorItem? = null

    private var pluginGameList = arrayListOf<GameEntity>()

    private var displayingGameIdSet = hashSetOf<String>() // 当前正在显示的游戏 id 列表

    var isLoadingPKData = false

    val customPluginItemLiveData: LiveData<CustomPluginItem> = MediatorLiveData<CustomPluginItem>().apply {
        addSource(PackageRepository.gameUpdateLiveData) {
            refreshPluginIfNeed(it)?.let(this::setValue)
        }
    }

    val recentGamesItemLiveData: LiveData<CustomRecentGamesItem> = MediatorLiveData<CustomRecentGamesItem>().apply {
        addSource(DownloadManager.getInstance().downloadEntityLiveData) {
            refreshRecentVGameIfNeed()?.let(this::setValue)
        }
        addSource(PackageRepository.recentVaPlayedChanged) {
            refreshRecentVGameIfNeed()?.let(this::setValue)
        }
    }

    val recentMiniGamesItemLiveData: LiveData<CustomRecentWeChatMiniGamesItem> =
        MediatorLiveData<CustomRecentWeChatMiniGamesItem>().apply {
            addSource(MiniGameRecentlyPlayUseCase.wechatRecentGamesItemLiveData) {
                refreshRecentWechatMiniGameIfNeed(it)?.let(this::setValue)
            }
        }

    val recentQqMiniGamesItemLiveData: LiveData<CustomRecentQqMiniGamesItem> =
        MediatorLiveData<CustomRecentQqMiniGamesItem>().apply {
            addSource(MiniGameRecentlyPlayUseCase.qqRecentGamesItemLiveData) {
                refreshRecentQQMiniGameIfNeed(it)?.let(this::setValue)
            }
        }

    val customDiscoverItemLiveData: LiveData<CustomDiscoverCardItem> =
        MediatorLiveData<CustomDiscoverCardItem>().apply {
            addSource(shareRepository.discoverData) {
                refreshDiscoverDataIfNeed(it)?.let(this::setValue)
            }
        }

    val customRecentAcceleratorItemLiveData: LiveData<CustomRecentAcceleratorItem> =
        MediatorLiveData<CustomRecentAcceleratorItem>().apply {
            addSource(shareRepository.recentlyAcctRecord) {
                refreshRecentAcceleratorItemIfNeed(it)?.let(this::setValue)
            }
        }

    val wechatMiniGameCPMItemLiveData: LiveData<Pair<String, List<GameEntity>>> =
        wGameSubjectCPMListUseCase.wechatMiniGameCPMListLiveData

    val hiddenNotifications: LiveData<HashMap<String, MutableSet<String>>>
        get() = shareRepository.hiddenNotifications


    val pkDataListLiveData = MutableLiveData<List<PKEntity>>()

    private val _dspGameList = NonStickyMutableLiveData<Pair<String, List<GameEntity>>>()
    val dspSubjectLiveData: LiveData<Pair<String, List<GameEntity>>> = _dspGameList

    private var lastComponentType = ""
    private var lastSubjectId = ""
    private var gameChildPosition = 0

    private fun refreshPluginIfNeed(updateList: List<GameUpdateEntity>): CustomPluginItem? {
        val gameList = arrayListOf<GameEntity>()
        updateList.forEach {
            if (it.isPluggable && it.indexPlugin == "open" && it.isShowPlugin(PluginLocation.only_index)) {
                val game = it.transformGameEntity()
                if (HomePluggableHelper.showHomePluggable(game)) {
                    game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
                    gameList.add(game)
                }
            }
        }
        // 下载七天排序
        gameList.sortWith { o1, o2 -> o2.download - o1.download }
        pluginGameList = gameList
        return pluginItem?.let { plugin ->
            pluginItem = CustomPluginItem(plugin.link, pluginGameList, plugin.position, plugin.componentPosition)
            pluginItem
        }
    }

    private fun refreshRecentVGameIfNeed(): CustomRecentGamesItem? {
        return recentItem?.let {
            val entities = VHelper.getSortedRecentlyPlayedList()
            recentItem = CustomRecentGamesItem(it.link, entities, it.position, it.componentPosition)
            recentItem
        }
    }

    private fun refreshRecentQQMiniGameIfNeed(list: List<GameEntity>): CustomRecentQqMiniGamesItem? {
        return recentQQItem?.let {
            recentQQItem =
                CustomRecentQqMiniGamesItem(
                    it.link,
                    list,
                    it.linkQqGameRecentlyPlayed,
                    it.position,
                    it.componentPosition
                )
            recentQQItem
        }
    }

    private fun refreshRecentWechatMiniGameIfNeed(list: List<GameEntity>): CustomRecentWeChatMiniGamesItem? {
        return recentWechatItem?.let {
            recentWechatItem = CustomRecentWeChatMiniGamesItem(it.link, list, it.position, it.componentPosition)
            recentWechatItem
        }
    }

    private fun refreshDiscoverDataIfNeed(discoveryCardEntity: DiscoveryCardEntity): CustomDiscoverCardItem? {
        return discoverCardItem?.let {
            discoverCardItem = CustomDiscoverCardItem(it.link, discoveryCardEntity, it.position, it.componentPosition)
            discoverCardItem
        }
    }

    private fun refreshRecentAcceleratorItemIfNeed(data: List<AcctRecord>): CustomRecentAcceleratorItem? {
        return recentAcceleratorItem?.let {
            recentAcceleratorItem =
                CustomRecentAcceleratorItem(it.link, data, it.moreLink, it.position, it.componentPosition)
            recentAcceleratorItem
        }
    }

    fun loadSuspendedWindow(pageId: String): Single<List<FloatingWindowEntity>> =
        remoteDataSource.loadSuspendedWindow(pageId)
            .map {
                localDataSource.filterWindows(it)
            }

    fun loadPullDownPush(pageId: String): Single<PullDownPush> = remoteDataSource.loadPullDownPush(pageId)

    fun loadFirstCustomPageData(
        pageId: String,
        forceLoad: Boolean
    ): Single<Pair<CustomPageData, List<CustomPageItem>>> {
        pageInfo.reset()
        lastComponentType = ""
        lastSubjectId = ""
        gameChildPosition = 0
        displayingGameIdSet.clear()
        isLoadingPKData = false
        return remoteDataSource.loadCustomPageData(pageId, pageInfo.page, forceLoad)
            .map {
                it to transformRawDataIntoItemData(it, forceLoad)
            }
    }

    fun loadNextCustomPageData(pageId: String): Single<List<CustomPageItem>> =
        remoteDataSource.loadCustomPageData(pageId, pageInfo.page)
            .map {
                transformRawDataIntoItemData(it, true)
            }

    private fun transformRawDataIntoItemData(data: CustomPageData, reloadDiscoverData: Boolean): List<CustomPageItem> {
        val list = arrayListOf<CustomPageItem>()
        val pkIdList = arrayListOf<String>()

        data.customsComponents
            .forEachIndexed { _, item ->
                // 如果当前item不是展开大图，并且上一个item为展开大图，则说明展开大图组件已结束
                if (lastComponentType == CUSTOM_LINK_TYPE_GAME && item.link.type != CUSTOM_LINK_TYPE_GAME) {
                    pageInfo.componentPositionIncrement()
                }

                when {
                    item.game != null -> {
                        if (!RegionSettingHelper.shouldThisGameBeFiltered(item.game.id)) {
                            // 记录当前游戏 ID 正在显示中
                            displayingGameIdSet.add(item.game.id)

                            // 如果当前item组件id不等于上一个item的组件id，则说明这是展开大图的第一个item
                            if (lastSubjectId != item.linkColumn?.id) {
                                gameChildPosition = 0
                            }
                            // 如果当前item为展开大图，并且上一个item也是展开大图，但是组件id不同，则说明这是一个新的并且连续的展开大图组件
                            if (lastComponentType == item.link.type && lastSubjectId != item.linkColumn?.id) {
                                pageInfo.componentPositionIncrement()
                            }
                            item.game.gameLocation = GameEntity.GameLocation.INDEX
                            list.add(
                                CustomGameItem(
                                    item.link,
                                    item.game,
                                    item.linkColumn,
                                    gameChildPosition,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            gameChildPosition++
                            pageInfo.positionIncrement()

                            lastSubjectId = item.linkColumn?.id ?: ""
                        }
                    }

                    item.link.type == CUSTOM_LINK_TYPE_COLUMN
                            || item.link.type == CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL
                            || item.link.type == CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL -> {
                        val subItems = convertColumnDetailSubjectItems(
                            pageInfo.position,
                            pageInfo.componentPosition,
                            item.link,
                            item.gameSubjectEntity
                        )
                        if (subItems.isNotEmpty()) {
                            list.addAll(subItems)
                            pageInfo.positionGetAndAdd(subItems.size)
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    //QQ小游戏-最近在玩(需要用户登录才显示)
                    item.link.type == CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED -> {
                        val linkQqGameRecentlyPlayed = item.linkQqGameRecentlyPlayed
                        if (linkQqGameRecentlyPlayed != null) {
                            recentQQItem = CustomRecentQqMiniGamesItem(
                                item.link,
                                MiniGameRecentlyPlayUseCase.getRecentlyPlayedMiniGameList(Constants.QQ_MINI_GAME),
                                linkQqGameRecentlyPlayed,
                                pageInfo.position,
                                pageInfo.componentPosition
                            ).also(list::add)
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    // 微信小游戏-最近在玩
                    item.link.type == CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED -> {
                        recentWechatItem = CustomRecentWeChatMiniGamesItem(
                            item.link,
                            MiniGameRecentlyPlayUseCase.getRecentlyPlayedMiniGameList(Constants.WECHAT_MINI_GAME),
                            pageInfo.position,
                            pageInfo.componentPosition
                        ).also(list::add)
                        pageInfo.positionIncrement()
                        pageInfo.componentPositionIncrement()
                    }

                    // 微信小游戏CPM专题
                    item.link.type == CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL -> {
                        item.gameSubjectEntity?.let { subject ->
                            list.add(
                                CustomWeChatMiniGamesCPMSubjectItem(
                                    item.link,
                                    subject,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            wGameSubjectCPMListUseCase.getWechatMiniGameCPMList(subject.id, subject.size.limit, subject.onlyFee)
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    // DSP 专题
                    item.link.type == CUSTOM_LINK_TYPE_DSP_GAME_COLUMN -> {
                        item.linkDspGameColumn?.let { subject ->
                            list.add(
                                CustomDspPlaceholderItem(
                                    item.link,
                                    subject,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            dspSubjectUseCase.getDspGames(subject.columnType, subject.size.index)
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(object : BiResponse<List<GameEntity>>() {
                                    override fun onSuccess(data: List<GameEntity>) {
                                        for (game in data) {
                                            game.subjectId = subject.id
                                            game.subjectName = subject.name
                                        }
                                        _dspGameList.value = subject.id!! to data
                                    }
                                })
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    item.linkColumnCollection != null -> {
                        // 专题合集
                        val linkColumnCollection = item.linkColumnCollection
                        linkColumnCollection.data = linkColumnCollection.data
                            .filter {
                                when (linkColumnCollection.style) {
                                    COMPONENTS_COLLECTION_STYLE_REFRESH_SLIDE_LIST ->
                                        it.games.size >= 4

                                    COMPONENTS_COLLECTION_STYLE_REFRESH_ICONS_4_2 -> {
                                        val needGameCount = linkColumnCollection.styleSetting.rowsNum * 4
                                        it.games.size >= needGameCount
                                    }

                                    else -> it.games.isNotEmpty()
                                }

                            }
                        val show = when (linkColumnCollection.style) {
                            COMPONENTS_COLLECTION_STYLE_RANKING_LIST,
                            COMPONENTS_COLLECTION_STYLE_X_SLIDE_CARD,
                            COMPONENTS_COLLECTION_STYLE_X_SLIDE_CARD_SMALL,
                            COMPONENTS_COLLECTION_STYLE_CAROUSEL -> linkColumnCollection.data.size > 1

                            else -> linkColumnCollection.data.isNotEmpty()
                        }
                        linkColumnCollection.data.forEach {
                            it.games.forEach { game ->
                                game.gameLocation = GameEntity.GameLocation.INDEX
                            }
                        }
                        if (show) {
                            list.add(
                                CustomSubjectCollectionItem(
                                    item.link,
                                    item.linkColumnCollection,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    item.linkGameListCollection != null -> {
                        // 游戏单合集
                        val linkGameListCollection = item.linkGameListCollection
                        fun isCarouselStyle() = linkGameListCollection.style == COMPONENTS_COLLECTION_STYLE_CAROUSEL
                        linkGameListCollection.data = linkGameListCollection.data
                            .filter {
                                it.games.isNotEmpty() || isCarouselStyle()
                            }
                        // 如果是轮播图样式，需要不少于三个，才会展示
                        val show =
                            !(isCarouselStyle() && linkGameListCollection.data.size < 3)
                        if (show && linkGameListCollection.data.isNotEmpty()) {
                            list.add(
                                CustomSubjectCollectionItem(
                                    item.link,
                                    item.linkGameListCollection,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }

                    }

                    item.linkCommonCollection != null -> {  // 通用内容合集
                        val layout = item.linkCommonCollection.layout
                        if (layout == COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_BANNER
                            || layout == COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_VERTICAL_CARD
                            || layout == COMMON_CONTENT_COLLECTION_LAYOUT_VERTICAL_IMAGE_TEXT
                        ) {
                            val subItems = convertSplitCommonContentCollection(item)
                            list.addAll(subItems)
                            pageInfo.positionGetAndAdd(subItems.size)
                            pageInfo.componentPositionIncrement()
                        } else {
                            var show = true
                            when (layout) {
                                COMMON_CONTENT_COLLECTION_LAYOUT_BANNER -> {
                                    // 轮播图右边卡片列表, 至少需要2个卡片才能显示
                                    val subSlideList = item.linkCommonCollection.slides.subSlide
                                    if (subSlideList.size > 1) {
                                        subSlideList.forEach {
                                            if (it.cardData.games.isNotEmpty()) {
                                                it.cardData.games = RegionSettingHelper.filterGame(it.cardData.games)
                                            }
                                        }
                                    }
                                }

                                COMMON_CONTENT_COLLECTION_LAYOUT_NOTIFICATION_COLUMN -> {
                                    // 通知栏目 初始化通知栏配置
                                    shareRepository.initHiddenNotifications()
                                }

                                COMMON_CONTENT_COLLECTION_LAYOUT_RECOMMEND_CARD -> {
                                    // 推荐卡片，小于两条数据不显示
                                    if (item.linkCommonCollection.recommendCards.size < 2) {
                                        show = false
                                    }
                                }

                            }

                            if (show) {
                                list.add(
                                    CustomCommonContentCollectionItem(
                                        item.link,
                                        item.linkCommonCollection,
                                        pageInfo.position,
                                        pageInfo.componentPosition
                                    )
                                )
                                pageInfo.positionIncrement()
                                pageInfo.componentPositionIncrement()
                            }


                        }

                    }

                    item.link.type == "cwzs_recently_played" -> {
                        // 最近在玩
                        val entities = VHelper.getSortedRecentlyPlayedList()
                        recentItem =
                            CustomRecentGamesItem(
                                item.link,
                                entities,
                                pageInfo.position,
                                pageInfo.componentPosition
                            ).also {
                                list.add(it)
                                pageInfo.positionIncrement()
                                pageInfo.componentPositionIncrement()
                            }
                    }

                    item.link.type == CUSTOM_LINK_TYPE_ACCELERATOR_RECENTLY_PLAYED -> {
                        // 最近在玩-加速器
                        val acctGameInfos = shareRepository.loadRecentlyAcctGameInfos()
                        recentAcceleratorItem = CustomRecentAcceleratorItem(
                            item.link,
                            acctGameInfos,
                            item.linkAcceleratorRecentlyPlayed?.moreLink,
                            pageInfo.position,
                            pageInfo.componentPosition
                        ).also {
                            list.add(it)
                        }

                        pageInfo.positionIncrement()
                        pageInfo.componentPositionIncrement()
                    }

                    item.link.type == "plugin_area" -> {
                        // 插件化区域
                        pluginItem =
                            CustomPluginItem(item.link, pluginGameList, pageInfo.position, pageInfo.componentPosition)
                                .also {
                                    list.add(it)
                                    pageInfo.positionIncrement()
                                    pageInfo.componentPositionIncrement()
                                }

                    }

                    item.homeItemTestV2 != null -> {
                        // 新游开测
                        list.add(
                            CustomGameTestV2Item(
                                item.link,
                                item.homeItemTestV2,
                                pageInfo.position,
                                pageInfo.componentPosition
                            )
                        )
                        pageInfo.positionIncrement()
                        pageInfo.componentPositionIncrement()
                    }

                    item.link.type == CUSTOM_LINK_TYPE_HALO_RECOMMEND -> {
                        // 光环推荐
                        val discoverCardEntity = shareRepository.discoverData.value
                        discoverCardItem =
                            CustomDiscoverCardItem(
                                item.link,
                                discoverCardEntity,
                                pageInfo.position,
                                pageInfo.componentPosition
                            )
                                .also {
                                    list.add(it)
                                    pageInfo.positionIncrement()
                                }
                        // 刷新光环推荐
                        if (reloadDiscoverData || discoverCardEntity == null) {
                            shareRepository.loadDiscoverCard()
                        }

                        pageInfo.componentPositionIncrement()
                    }

                    item.contentCard != null -> {
                        // 内容卡片
                        list.add(
                            CustomContentCardItem(
                                item.link,
                                item.contentCard,
                                pageInfo.position,
                                pageInfo.componentPosition
                            )
                        )
                        pageInfo.positionIncrement()
                        pageInfo.componentPositionIncrement()
                    }

                    item.linkTopGameComments != null -> {
                        // 安利墙
                        //如果评论预览的三行之中有至少有两行的字数均少于15个字，则该评论不在安利墙 展示，顺位由下一个游戏评论顶替（评论引导标签也需要加入字数计算

                        val comments = item.linkTopGameComments.filter {
                            val m = Pattern.compile(RatingEditActivity.LABEL_REGEX).matcher(it.comment.content)
                            if (m.find()) {
                                val contents = TextHelper.getCommentLabelSpannableStringBuilder(
                                    it.comment.content,
                                    com.gh.gamecenter.common.R.color.text_theme
                                )
                                val splits = contents.split("\n")
                                splits.take(3).filter { split ->
                                    split.length >= AMWAY_COMMENT_MIN_LENGTH
                                }.size >= 2
                            } else {
                                val content = it.comment.content
                                val tvWidth = DisplayUtils.getScreenWidth() - 108f.dip2px()
                                val paint = Paint()
                                paint.isLinearText
                                paint.textSize = 14f.sp2px().toFloat()
                                val resultList = arrayListOf<String>()
                                val splits = content.split("\n")
                                splits.forEach { split ->
                                    var itemContent = split
                                    if (itemContent.length <= 15) {
                                        resultList.add(itemContent)
                                    } else {
                                        while (itemContent.length > 15) {
                                            val charCount = paint.breakText(itemContent, true, tvWidth.toFloat(), null)
                                            val result = itemContent.substring(0, charCount)
                                            resultList.add(result)
                                            if (charCount < content.length) {
                                                itemContent = itemContent.substring(charCount, itemContent.length)
                                            }
                                            if (resultList.size >= 3) {
                                                return@forEach
                                            }
                                        }
                                    }
                                }
                                resultList.filter { result ->
                                    result.length >= AMWAY_COMMENT_MIN_LENGTH
                                }.size >= 2
                            }
                        }
                        if (comments.isNotEmpty()) {
                            list.add(
                                CustomAmwayItem(
                                    item.link,
                                    comments,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    item.link.type == CUSTOM_LINK_TYPE_PK -> {
                        // PK
                        if (!item.link.link.isNullOrEmpty()) {
                            list.add(
                                CustomPKItem(
                                    item.link,
                                    item.linkPK,
                                    pageInfo.position,
                                    pageInfo.componentPosition
                                )
                            )
                            pkIdList.add(item.link.link!!)
                            pageInfo.positionIncrement()
                            pageInfo.componentPositionIncrement()
                        }
                    }

                    else -> {
                        CustomInvalidItem
                    }
                }
                lastComponentType = item.link.type ?: ""
            }

        pageInfo.nextPage()

        if (pkIdList.isNotEmpty()) {
            loadPKData(pkIdList)
        }

        return list
    }

    fun convertColumnDetailSubjectItems(
        position: Int,
        componentPosition: Int,
        link: LinkEntity,
        subjectEntity: SubjectEntity?,
    ): List<CustomPageItem> {

        var currentPosition = position
        val list = mutableListOf<CustomPageItem>()

        // 游戏专题
        val gameSubject = subjectEntity?.also {
            if (link.type == CUSTOM_LINK_TYPE_COLUMN) {
                it.data?.forEach { game ->
                    game.gameLocation = GameEntity.GameLocation.INDEX
                }
            }
        }

        if (gameSubject != null && !gameSubject.data.isNullOrEmpty()) {
            // 替换游戏
            substituteGameIfNeeded(gameSubject)

            // 记录已显示的游戏 id
            for (game in gameSubject.data!!) {
                displayingGameIdSet.add(game.id)
            }

            when (gameSubject.type) {
                COMPONENTS_GAME_SUBJECT_TYPE_DOUBLE_CARD, COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD, COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT -> {
                    // 双列卡片  双列福利卡片 竖式图文列表
                    val gameCount = gameSubject.data?.size ?: 0
                    if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
                        val isMustFullyCover = gameSubject.type == COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT
                        val subjectItems =
                            convertSplitSubjectItems(
                                link,
                                subjectEntity,
                                currentPosition,
                                componentPosition,
                                2,
                                isMustFullyCover
                            )
                        list.addAll(subjectItems)
                        currentPosition += subjectItems.size
                    }
                }

                COMPONENTS_GAME_SUBJECT_TYPE_GAME_VERTICAL -> {
                    // 长列表式
                    val subjectItems =
                        convertSplitSubjectItems(link, subjectEntity, currentPosition, componentPosition, 1, false)
                    list.addAll(subjectItems)
                    currentPosition += subjectItems.size
                }

                COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL -> {
                    // 图标矩阵
                    val subjectItems =
                        convertSplitSubjectItems(link, subjectEntity, currentPosition, componentPosition, 4, true)
                    list.addAll(subjectItems)
                    currentPosition += subjectItems.size
                }

                else -> {
                    if (gameSubject.type == COMPONENTS_GAME_SUBJECT_TYPE_GAME_VIDEO_HORIZONTAL_SLIDE ||
                        gameSubject.type == COMPONENTS_SUBJECT_TYPE_GAME_FOLD_SLIDE
                    ) {
                        val gameCount = gameSubject.data?.size ?: 0
                        if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
                            list.add(
                                CustomSubjectItem(
                                    link,
                                    gameSubject,
                                    currentPosition,
                                    componentPosition
                                )
                            )
                        }

                    } else {
                        val gameCount = gameSubject.data?.size ?: 0
                        if (gameCount > 0) {
                            list.add(
                                CustomSubjectItem(
                                    link,
                                    gameSubject,
                                    currentPosition,
                                    componentPosition
                                )
                            )
                        }
                    }
                }
            }
        }
        return list
    }


    private fun convertSplitSubjectItems(
        link: LinkEntity,
        subjectEntity: SubjectEntity?,
        position: Int,
        componentPosition: Int,
        stepNum: Int,
        isMustFullyCover: Boolean
    ): List<CustomPageItem> {
        val gameSubject = subjectEntity ?: return emptyList()
        val items = arrayListOf<CustomPageItem>()
        val games = gameSubject.data ?: emptyList()
        var currentPosition = position
        (games.indices step stepNum).forEach { start ->
            if (isMustFullyCover) {
                if (start + stepNum - 1 < games.size) {
                    items.add(
                        CustomSplitSubjectItem(
                            link,
                            gameSubject,
                            currentPosition++,
                            componentPosition,
                            stepNum,
                            start
                        )
                    )
                }
            } else {
                items.add(
                    CustomSplitSubjectItem(
                        link,
                        gameSubject,
                        currentPosition++,
                        componentPosition,
                        stepNum,
                        start
                    )
                )
            }
        }
        items.forEach {
            if (it is CustomSplitSubjectItem) {
                it.splitItemCount = items.size
            }
        }
        return items
    }

    private fun convertSplitCommonContentCollection(item: CustomPageData.CustomsComponent): List<CustomSplitCommonContentCollectionItem> {
        val linkCommonCollection = item.linkCommonCollection ?: return emptyList()
        val data = linkCommonCollection.data
        val items = arrayListOf<CustomSplitCommonContentCollectionItem>()
        (data.indices step 2).forEach { left ->
            items.add(
                CustomSplitCommonContentCollectionItem(
                    item.link,
                    linkCommonCollection,
                    pageInfo.position,
                    pageInfo.componentPosition,
                    left
                )
            )
        }
        return items
    }

    fun loadCollectionContent(item: CustomSubjectCollectionItem): Single<List<CustomPageData.LinkColumnCollection.CustomSubjectEntity>> =
        remoteDataSource.loadCollectionContent(item)
            .map {
                it.apply {
                    firstOrNull()?.run { games = RegionSettingHelper.filterGame(games) }
                }
            }

    fun notifyPositionAdded(offset: Int) {
        pageInfo.positionGetAndAdd(offset)
    }

    fun notifyPositionChanged(value: Int) {
        pageInfo.position = value
    }

    fun loadChangeSubjectGame(subjectEntity: SubjectEntity): Observable<List<GameEntity>> =
        remoteDataSource.loadChangeSubjectGame(subjectEntity)
            .map(RegionSettingHelper.filterGame)
            .map(ApkActiveUtils.filterMapperList)

    fun loadChangeSubjectWGameCPM(page: Int, minimumSize: Int, onlyFee: Boolean): Observable<MutableList<GameEntity>> =
        wGameSubjectCPMRemoteDataSource.getEditorRecommendCPMList(page = page, minimumSize = minimumSize, onlyFee = onlyFee)// 微信小游戏CPM专题的“换一批”接口
            .toObservable()
            .map(RegionSettingHelper.filterGame)
            .map(ApkActiveUtils.filterMapperList)

    fun loadSlideDiscoverCardGames(): Observable<List<GameEntity>> =
        remoteDataSource.loadSlideDiscoverCardGames()
            .map(RegionSettingHelper.filterGame)

    @SuppressLint("CheckResult")
    fun loadPKData(pkIdList: List<String>) {
        isLoadingPKData = true
        remoteDataSource.loadPKData(pkIdList)
            .timeout(5, TimeUnit.SECONDS)
            .compose(singleToMain())
            .subscribe({
                isLoadingPKData = false
                pkDataListLiveData.value = it
            }, {
                isLoadingPKData = false
            })
    }

    fun postPKVote(pkId: String, isPositive: Boolean): Single<ResponseBody> =
        remoteDataSource.postPKVote(pkId, isPositive)

    /**
     * 部分样式的专题，当替换游戏功能启用时需要尝试替换游戏
     *
     * 仅针对专题样式为“长列表式、滑动列表、图标矩阵、图标泳道、~~静态图集、横向滚动图集~~”生效
     * https://jira.shanqu.cc/browse/GHZS-3966
     */
    private fun substituteGameIfNeeded(gameSubject: SubjectEntity) {
        if (!gameSubject.relatedColumnId.isNullOrEmpty() && gameSubject.data != null) {
            when (gameSubject.type) {
                COMPONENTS_GAME_SUBJECT_TYPE_GAME_VERTICAL,
                COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_SLIDE,
                COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL,
                COMPONENTS_SUBJECT_TYPE_GAME_TIMELINE_HORIZONTAL_SLIDE,
                COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL_SLIDE,
                COMPONENTS_SUBJECT_TYPE_GALLERY,
                COMPONENTS_SUBJECT_TYPE_GALLERY_SLIDE
                    -> {
                    GameSubstituteRepositoryHelper.replaceGames(
                        gameList = gameSubject.data!!,
                        displayingGameIdSet = displayingGameIdSet,
                        relatedCollectionId = gameSubject.relatedColumnId!!
                    )
                }
            }
        }
    }

    fun hideNotificationItem(id: String, itemId: String) {
        shareRepository.hideNotificationItem(id, itemId)
    }

    /**
     * 分页信息
     * @param page 页码
     * @param position 当前数据在ui界面的最后一个位置
     * @param componentPosition 当前组件所在的位置
     */
    class PageInfo {

        private var _page: Int = 1
        val page: Int
            get() = _page

        private var _position: AtomicInteger = AtomicInteger(0)
        var position: Int
            get() = _position.get()
            set(value) {
                _position.set(value)
            }

        private var _componentPosition: AtomicInteger = AtomicInteger(0)
        val componentPosition: Int
            get() = _componentPosition.get()


        fun nextPage() {
            _page++
        }

        fun positionIncrement() {
            positionGetAndAdd(1)
        }

        fun componentPositionIncrement() {
            componentPositionGetAndAdd(1)
        }

        fun positionGetAndAdd(value: Int) {
            _position.getAndAdd(value)
        }

        fun componentPositionGetAndAdd(value: Int) {
            _componentPosition.getAndAdd(value)
        }

        fun reset() {
            _page = 1
            _position.set(0)
            _componentPosition.set(0)
        }
    }

    fun onClear() {
        compositeDisposable.clear()
    }

    companion object {

        private const val COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT = 2
        private const val AMWAY_COMMENT_MIN_LENGTH = 15

        fun newInstance() = CustomPageRepository(
            CustomPageRemoteDataSource(
                RetrofitManager.getInstance().api,
                RetrofitManager.getInstance().newApi,
                MainWrapperRepository.getInstance()
            ),
            CustomPageLocalDataSource(),
            WGameSubjectCPMRemoteDataSource(),
        )
    }
}
