local DungeonBaseEntity = require "app/userdata/dungeon/dungeon_base_entity"
local DungeonArmorEntity = class("DungeonArmorEntity", DungeonBaseEntity)

local FUND_AD_REWARD_ID = 1

-- 支线副本数据
function DungeonArmorEntity:clear()
    DataManager:unregisterCrossDayFunc("DungeonArmorEntity")
end

function DungeonArmorEntity:init(data)
    Logger.logHighlight("-----DungeonArmorEntity------")
    Logger.printTable(data)
    self.maxPassedId = data.max_challenge_id or 0
    self.armorInfo = data.armor_info or {}
    self.farmCount = data.farm_count or {}
    self.heroes = data.heroes or {}
    self.starRewards = data.star_rewards or {}
    self.fundRewards = data.fund_rewards
    self.totalChallengeCount = data.total_challenge_count

    self:updateGift(data.gift_info, true)
    DataManager.FormationData:initDungeonArmor(self.heroes)

    DataManager:registerCrossDayFunc("DungeonArmorEntity", function()
        self.fundRewards[FUND_AD_REWARD_ID] = false
        self.farmCount = table.clearOrCreate(self.farmCount)
        self:setDirty()
    end)
end

function DungeonArmorEntity:refreshInfoOnSettlement(chapterId, result)
    if result.max_id > self.maxPassedId then
        ModuleManager.TaskManager:addTaskProgress(GConst.TaskConst.TASK_TYPE.X_DUNGEON_ARMOR, result.max_id - self.maxPassedId)
    end
    self.totalChallengeCount[chapterId] = (self.totalChallengeCount[chapterId] or 0) + 1
    self.maxPassedId = result.max_id
    self.armorInfo[chapterId] = result.armor_info
    self:updateGift(result.gift_info)
    self:setDirty()
end

function DungeonArmorEntity:refreshInfoOnFarm(chapterId, result)
    self.farmCount[chapterId] = (self.farmCount[chapterId] or 0) + 1
    self:updateGift(result.gift_info)
    self:setDirty()
end

function DungeonArmorEntity:refreshFarmCount(chapterId, count)
    if not count then
        return
    end
    self.farmCount[chapterId] = count
    self:setDirty()
end

-- 更新礼包状态
function DungeonArmorEntity:updateGift(giftInfo, isInit)
    DataManager.ShopData:initGift(PayManager.PURCHARSE_ACT_TYPE.ARMOR_GIFT, giftInfo, isInit)
end

function DungeonArmorEntity:setStarReward(starId)
    self.starRewards[starId] = true
    self:setDirty()
end

function DungeonArmorEntity:setDirty()
    self.data.isDirty = not self.data.isDirty
end

function DungeonArmorEntity:getTotalChallengeCount()
    local count = 0
    for _, c in pairs(self.totalChallengeCount) do
        count = count + 1
    end
end

function DungeonArmorEntity:getTodayChallengeCount()
    return 0
end

function DungeonArmorEntity:getPassedMaxId()
    return self.maxPassedId
end

function DungeonArmorEntity:getIsAllTimeOpen()
    return true
end

function DungeonArmorEntity:getModuleKey()
    return ModuleManager.MODULE_KEY.DUNGEON_ARMOR
end

function DungeonArmorEntity:getConfig(chapterId)
    return ConfigManager:getConfig(self:getConfigName())[chapterId]
end

function DungeonArmorEntity:getConfigName()
    return "chapter_dungeon_armor"
end

function DungeonArmorEntity:getTitleString()
    return I18N:getGlobalText(I18N.GlobalConst.DUNGEON_ARMOR_DESC_1)
end

function DungeonArmorEntity:getRuleString()
    return I18N:getGlobalText(I18N.GlobalConst.DUNGEON_ARMOR_DESC_2)
end

function DungeonArmorEntity:getOpenWeekString()
    return I18N:getGlobalText(I18N.GlobalConst.DUNGEON_ARMOR_DESC_3)
end

function DungeonArmorEntity:getBanner()
    return "assets/arts/textures/background/dungeon/dungeon_bg_4.png"
end

function DungeonArmorEntity:getOpenTextColor()
    return "#FFFFFF"
end

function DungeonArmorEntity:getChallengeHpCost()
    return GFunc.getConstReward("dungeon_armor_limit")
end

function DungeonArmorEntity:isNoTotalLimit()
    return true
end

function DungeonArmorEntity:isNotShowLimitCount()
    return true
end

function DungeonArmorEntity:onClickFight()
    ModuleManager.DungeonArmorManager:showMainUI()
end

function DungeonArmorEntity:getStagePassEnough(chapterId)
    local config = self:getConfig(chapterId)
    if not config then
        return false
    end

    if config.main_chapter and not DataManager.ChapterData:getChapterPassed(config.main_chapter) then
        return false, DataManager.ChapterData:getMaxChapterId(), config.main_chapter
    end

    return true
end

function DungeonArmorEntity:canFightChapter(chapterId)
    if not chapterId then
        return false
    end

    if chapterId <= self.maxPassedId + 1 then
        if self:getStagePassEnough(chapterId) then
            return true
        end
    end

    return false
end

function DungeonArmorEntity:canFarmChapter(chapterId)
    if not chapterId then
        return false
    end

    if self.maxPassedId >= chapterId then
        if self:getStarNum(chapterId) >= 3 then
            return true
        end
    end

    return false
end

function DungeonArmorEntity:getDialyFarmLimit(chapterId)
    local config = self:getConfig(chapterId)
    if not config then
        return 0
    end
    return config.sweep
end

function DungeonArmorEntity:getFarmCount(chapterId)
    return self.farmCount[chapterId] or 0
end

function DungeonArmorEntity:getRemianFarmCount(chapterId)
    local count = self:getDialyFarmLimit(chapterId) - self:getFarmCount(chapterId)
    if count < 0 then
        count = 0
    end
    return count
end

function DungeonArmorEntity:getStarRewardGot(star)
    return self.starRewards[star]
end

function DungeonArmorEntity:getStarNum(chapterId)
    if not self.armorInfo[chapterId] then
        return 0
    end
    return #self.armorInfo[chapterId].stars
end

function DungeonArmorEntity:getAllStarNum()
    if not self.armorInfo then
        return 0
    end
    local count = 0
    for id, info in pairs(self.armorInfo) do
        count = count + #info.stars
    end
    return count
end

function DungeonArmorEntity:getMinStarTarget()
    local count = ConfigManager:getConfigNum("chapter_dungeon_armor_reward")
    local id
    local nextTarget

    for i = 1, count do
        if not self:getStarRewardGot(i) then
            id = i
            nextTarget = ConfigManager:getConfig("chapter_dungeon_armor_reward")[id].star
            break
        end
    end

    if not id then -- 全部领完
        id = count
        nextTarget = ConfigManager:getConfig("chapter_dungeon_armor_reward")[id].star
        return id, nextTarget, nextTarget
    end

    local starNum = self:getAllStarNum()
    local lastStarNum = 0
    local lastConfig = ConfigManager:getConfig("chapter_dungeon_armor_reward")[id - 1]
    if lastConfig then -- 不是第一个
        lastStarNum = lastConfig.star
    end
    local progress = starNum - lastStarNum
    local totalProgress = nextTarget - lastStarNum
    return id, progress, totalProgress
end

function DungeonArmorEntity:getStarDone(chapterId, index)
    if not self.armorInfo[chapterId] then
        return false
    end

    local stars = self.armorInfo[chapterId].stars
    if stars then
        for _, star in ipairs(stars) do
            if star == index then
                return true
            end
        end
    end
    return false
end

function DungeonArmorEntity:getStarReward(chapterId, index)
    local config = self:getConfig(chapterId)
    return config.star_task_reward[index]
end

function DungeonArmorEntity:getStarStarId(chapterId, index)
    local config = self:getConfig(chapterId)
    return config.star_task[index - 1]
end

function DungeonArmorEntity:getStarInfo(chapterId)
    return self.armorInfo[chapterId]
end

function DungeonArmorEntity:setCurFightChapterId(chapterId)
    self.curFightchapterId = chapterId or 1
end

function DungeonArmorEntity:getCurFightChapterId()
    return self.curFightchapterId or 1
end

function DungeonArmorEntity:getChapterFightCount(chapterId)
    return self.totalChallengeCount[chapterId] or 0
end

function DungeonArmorEntity:getTodayRemainLimitCount() -- 这里用作红点显示
    if self:canClaimStarReward() then
        return 1
    end

    return 0
end

function DungeonArmorEntity:canClaimStarReward()
    local id, progress, totalProgress = self:getMinStarTarget()
    if self:getStarRewardGot(id) then
        return false
    end

    return progress >= totalProgress
end

function DungeonArmorEntity:getMinLowThreeStarId()
    for id, _ in ipairs(ConfigManager:getConfig(self:getConfigName())) do
        local starNum = self:getStarNum(id)
        if starNum < 3 then
            return id
        end
    end

    return self.maxPassedId
end

function DungeonArmorEntity:formatTaskByController(battleBaseController, chapterId)
    local taskProgress = {}
    if not battleBaseController then
        return taskProgress
    end
    local pass = self:getPassedMaxId() >= chapterId and 1 or 0
    local hpp = math.floor(battleBaseController.battleData:getAtkTeam():getHpPercent() * 100 + 0.0001)
    local bossRoundCount = 0
    local waveIndex = battleBaseController:getWaveIndex()
    if waveIndex >= battleBaseController.maxWaveIndex then -- 最后一波
        bossRoundCount = battleBaseController.waveRoundCount[waveIndex] or 0
    end
    local totalRound = 0
    for wave, round in pairs(battleBaseController.waveRoundCount) do
        totalRound = totalRound + round
    end

    local config = ConfigManager:getConfig("task_dungeon_armor")
    taskProgress = {
        [0] = pass
    }
    if config then
        for id, info in pairs(config) do
            if info.type == 1 then
                taskProgress[id] = hpp
            elseif info.type == 2 then
                taskProgress[id] = bossRoundCount
            elseif info.type == 3 then
                taskProgress[id] = totalRound
            end
        end
    end

    return taskProgress
end

function DungeonArmorEntity:getTaskDesc(taskId, progress)
    local config = ConfigManager:getConfig("task_dungeon_armor")[taskId]
    if not config then
        return I18N:getGlobalText(I18N.GlobalConst.DUNGEON_ARMOR_DESC_7)
    end

    local desc = I18N:getConfig("task_dungeon_armor")[taskId].desc

    progress = progress or 0
    local taskNum = config.param
    local over = false
    if config.type == 1 then -- 特殊处理
        over = progress >= taskNum
        progress = progress .. "%"
        taskNum = taskNum .. "%"
    elseif config.type == 2 then
        over = progress <= taskNum
    elseif config.type == 3 then
        over = progress <= taskNum
    end
    local color = "#FF4949"
    if over then
        color = "#49FF49"
    end
    local progressStr = string.format("<color=%s>(%s/%s)</color>", color, progress, taskNum)
    return desc .. progressStr
end

function DungeonArmorEntity:getTaskDescByIndex(chapterId, index, battleBaseController, taskProgress)
    taskProgress = taskProgress or self:formatTaskByController(battleBaseController, chapterId)

    if not self.taskList then
        self.taskList = {}
    end
    if not self.taskList[chapterId] then
        self.taskList[chapterId] = GFunc.getTable(self:getConfig(chapterId).star_task)
        table.insert(self.taskList[chapterId], 1, 0) -- 首位添加默认任务
    end

    local taskId = self.taskList[chapterId][index]
    if not taskId then
        return GConst.EMPTY_STRING
    end

    local over = self:getStarDone(chapterId, index)
    return self:getTaskDesc(taskId, taskProgress[taskId]), over
end

-- 获取当前基金奖励所属阶段
function DungeonArmorEntity:getCurFundStage()
    local cfg = ConfigManager:getConfig("dungeon_armor_fund")
    for id, data in ipairs(cfg) do
        if id ~= FUND_AD_REWARD_ID and not self:isGotFundReward(id) then
            return data.stage
        end
    end

    return cfg[#cfg].stage
end

-- 基金是否有红点
function DungeonArmorEntity:isHasFundRedDot()
    return self:isCanWatchFundAd() or (self:isBoughtFundStage(self:getCurFundStage()) and self:hasCanGetFundReward())
end

-- 基金阶段是否已购买
function DungeonArmorEntity:isBoughtFundStage(stage)
    if not stage then
        return false
    end

    local giftId = self:getFundStageGiftId(stage)

    if not giftId then
        return false
    end

    local count = DataManager.ShopData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, giftId)

    if EDITOR_MODE then
        Logger.logHighlight("支线基金购买状态:"..giftId.."/"..count)
    end

    return count > 0
end

-- 获取基金阶段标题
function DungeonArmorEntity:getFundStageTitle()
    local stage = self:getCurFundStage()
    return I18N:getGlobalText("DUNGEON_ARMOR_FUND_" .. stage)
end

-- 获取基金阶段的礼包id
function DungeonArmorEntity:getFundStageGiftId(stage)
    local giftId
    for id, data in ipairs(ConfigManager:getConfig("dungeon_armor_fund")) do
        if data.stage == stage then
            giftId = data.act_gift
            break
        end
    end
    return giftId
end

-- 获取基金阶段奖励id列表
function DungeonArmorEntity:getFundStageRewardIds(stage)
    local result = {}

    for id, data in ipairs(ConfigManager:getConfig("dungeon_armor_fund")) do
        if data.stage == stage then
            table.insert(result, id)
        end
    end
    return result
end

-- 获取当前基金奖励列表（Sort）
function DungeonArmorEntity:getFundRewardIdsSort()
    local ids = self:getFundStageRewardIds(self:getCurFundStage())

    local unreceived = {}
    local received = {}

    for index, id in ipairs(ids) do
        if self:isGotFundReward(id) then
            table.insert(received, id)
        else
            table.insert(unreceived, id)
        end
    end
    table.sort(unreceived, function(a, b) return a < b end)
    table.sort(received, function(a, b) return a < b end)

    if not self:isGotFundReward(FUND_AD_REWARD_ID) then
        unreceived = table.addArray(self:getFundStageRewardIds(0), unreceived)
    end

    return table.addArray(unreceived, received)
end

-- 是否满足基金奖励条件
function DungeonArmorEntity:isMeetFundReward(id)
    if id == FUND_AD_REWARD_ID then
        return not self:isCanWatchFundAd()
    end

    local cfg = ConfigManager:getConfig("dungeon_armor_fund")[id]
    return cfg and self.maxPassedId >= cfg.dungeon_stage
end

-- 是否有可领取的基金奖励
function DungeonArmorEntity:hasCanGetFundReward()
    for index, id in ipairs(self:getFundRewardIdsSort(self:getCurFundStage())) do
        if self:isMeetFundReward(id) and not self:isGotFundReward(id) then
            return true
        end
    end
    return false
end

-- 是否已领取基金奖励
function DungeonArmorEntity:isGotFundReward(id)
    return self.fundRewards and self.fundRewards[id]
end

-- 今日是否可以看基金广告
function DungeonArmorEntity:isCanWatchFundAd()
    return not self:isGotFundReward(FUND_AD_REWARD_ID)
end

-- 基金奖励领取成功
function DungeonArmorEntity:onGetFundRewardSuccess(id)
    if not self.fundRewards then
        self.fundRewards = {}
    end
    self.fundRewards[id] = true
    self:setDirty()
end

-- 基金购买成功
function DungeonArmorEntity:onBuyFundSuccess()
    self:setDirty()
end

return DungeonArmorEntity