local HeroFundData = class("HeroFundData", BaseData)

local PRO_ACT_ID = 140403
local UTRAL_ACT_ID = 140404
local OPEN_AT_DAY = 3
local OPEN_DAY = 7

HeroFundData.REWARD_TYPE = {
    FREE = 1,
    PRO = 2,
    UTRAL = 3
}

function HeroFundData:ctor()
    self:clear()
end

function HeroFundData:clear()
    self.data.isDirty = false
    self.waveCount = 0                  -- 波次
    self.waveLevel = 0                  -- 波次等级 可领的最高等级
    self.freeLevel = 0                  -- 免费领取过的等级
    self.proLevel = 0                   -- 付费1领取过的等级
    self.utralLevel = 0                 -- 付费2领取过的等级
    self.free_awarded = {}              -- 领取过的免费id
    self.pay_low_awarded = {}           -- 领取过的付费1id
    self.pay_high_awarded = {}          -- 领取过的付费2id
    self.proBounght = false             -- 付费1已购买
    self.utralBounght = false           -- 付费2已购买
    self.waveLevelList = {}             -- 缓存波次等级
    self.waveLevelListCount = 0         -- 缓存最大等级
    self.endTime = 0                    -- 活动结束时间

    DataManager:unregisterCrossDayFunc("HeroFundData")
    DataManager:unregisterTryOpenFunc("HeroFundData")
end

function HeroFundData:init(data)
    data = data or {}
    self.waveCount = data.total_wave or 0
    self.endTime = 0
    if data.open_at and data.open_at > 0 then
        self.endTime = GFunc.formatTimeStep(data.open_at) + (OPEN_DAY + 1) * 86400
    end

    if data.funds then
        if data.funds.free_awarded then
            for _, id in ipairs(data.funds.free_awarded) do
                self:setFreeGot(id)
            end
        end

        if data.funds.pay_low_awarded then
            for _, id in ipairs(data.funds.pay_low_awarded) do
                self:setProGot(id)
            end
        end

        if data.funds.pay_high_awarded then
            for _, id in ipairs(data.funds.pay_high_awarded) do
                self:setUtralGot(id)
            end
        end
    end

    local cfg = self:getConfig()
    self.waveLevelListCount = 0
    for id, info in ipairs(cfg) do
        self.waveLevelList[id] = info.exp
        self.waveLevelListCount = self.waveLevelListCount + 1
    end

    for id = 1, self.waveLevelListCount do
        local wave = self.waveLevelList[id]
        if wave and wave <= self.waveCount then
            self.waveLevel = id
        else
            break
        end
    end

    self.proBounght = false
    self:getProBought()

    self.utralBounght = false
    self:getUtralBought()

    self:initTaskListener()

    if self.endTime ~= 0 then -- 开过了
        return
    end

    DataManager:registerTryOpenFunc("HeroFundData", function()
        if self.endTime ~= 0 then
            return
        end

        if ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.SEVEN_DAY, true) then
            local time = Time:getServerTime()
            local registerBeginTs = Time:getBeginningOfOneDay(DataManager:getRegisterTs())
            if registerBeginTs + (OPEN_AT_DAY - 1) * 86400 <= time then
                self.endTime = time + (OPEN_DAY + 1) * 86400
            end
            EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.MAIN_UI_CHECK_SIDE_BAR)
            self:setDirty()
            DataManager:unregisterTryOpenFunc("HeroFundData")
        end
    end)

    DataManager:registerCrossDayFunc("HeroFundData", function()
        if self.endTime ~= 0 then -- 开过了
            return
        end

        if not ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.SEVEN_DAY, true) then
            return
        end

        local time = Time:getServerTime()
        local registerBeginTs = Time:getBeginningOfOneDay(DataManager:getRegisterTs())
        if registerBeginTs + (OPEN_AT_DAY - 1) * 86400 <= time then
            self.endTime = time + (OPEN_DAY + 1) * 86400
        end
        EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.MAIN_UI_CHECK_SIDE_BAR)
        self:setDirty()
    end)
end

function HeroFundData:getConfig()
    return ConfigManager:getConfig("activity_herofund")
end

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

function HeroFundData:getIsOpen()
    if GFunc.isShenhe() then
        return false
    end
    if not ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.SEVEN_DAY, true) then
        return false
    end

    if self.endTime <= 0 then
        return false
    end

    return self.endTime > Time:getServerTime()
end

function HeroFundData:getRemainTime()
    local remian = math.max(0, self.endTime - Time:getServerTime())
    return remian
end

function HeroFundData:getWaveLevel()
    return self.waveLevel or 0
end

function HeroFundData:getLevelWave(level)
    return self.waveLevelList[level] or 0
end

function HeroFundData:addWaveCount(count)
    self.waveCount = self.waveCount + count

    local nextLevel = self.waveLevel + 1
    if self.waveLevelList[nextLevel] and self.waveCount >= self.waveLevelList[nextLevel] then -- 升级了
        for id = nextLevel, self.waveLevelListCount do
            local wave = self.waveLevelList[id]
            if wave and wave <= self.waveCount then
                self.waveLevel = id
            else
                break
            end
        end
    end

    self:setDirty()
end

function HeroFundData:getWaveCount()
    return self.waveCount or 0
end

function HeroFundData:getFreeGot(level)
    return self.free_awarded[level]
end

function HeroFundData:setFreeGot(level)
    if not self.free_awarded[level] then
        self.freeLevel = self.freeLevel + 1
    end
    self.free_awarded[level] = true
end

function HeroFundData:getProActId()
    return PRO_ACT_ID
end

function HeroFundData:getProPrice()
    local cfg = ConfigManager:getConfig("act_gift")[PRO_ACT_ID]
    if not cfg then
        return GConst.EMPTY_STRING
    end
    return GFunc.getFormatPrice(cfg.recharge_id)
end

function HeroFundData:getProGot(level)
    return self.pay_low_awarded[level]
end

function HeroFundData:setProGot(level)
    if not self.pay_low_awarded[level] then
        self.proLevel = self.proLevel + 1
    end
    self.pay_low_awarded[level] = true
end

function HeroFundData:getProBought()
    if not self.proBounght then
        if DataManager.ShopData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, PRO_ACT_ID) > 0 then
            self.proBounght = true
        end
    end

    return self.proBounght
end

function HeroFundData:setProBought()
    self.proBounght = true
    self:setDirty()
end

function HeroFundData:getUtralActId()
    return UTRAL_ACT_ID
end

function HeroFundData:gettUtralPrice()
    local cfg = ConfigManager:getConfig("act_gift")[UTRAL_ACT_ID]
    if not cfg then
        return GConst.EMPTY_STRING
    end
    return GFunc.getFormatPrice(cfg.recharge_id)
end

function HeroFundData:getUtralGot(level)
    return self.pay_high_awarded[level]
end

function HeroFundData:setUtralGot(level)
    if not self.pay_high_awarded[level] then
        self.utralLevel = self.utralLevel + 1
    end
    self.pay_high_awarded[level] = true
end

function HeroFundData:getUtralBought()
    if not self.utralBounght then
        if DataManager.ShopData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, UTRAL_ACT_ID) > 0 then
            self.utralBounght = true
        end
    end
    return self.utralBounght
end

function HeroFundData:setUtralBought()
    self.utralBounght = true
    self:setDirty()
end

function HeroFundData:gotReward(heroIdWithLv)
    if not heroIdWithLv then
        return
    end

    for _, info in ipairs(heroIdWithLv) do
        if info.grade == 0 then
            self:setFreeGot(info.id)
        elseif info.grade == 1 then
            self:setProGot(info.id)
        elseif info.grade == 2 then
            self:setUtralGot(info.id)
        end
    end

    self:setDirty()
end

function HeroFundData:getFreeCanGet(level)
    if self:getFreeGot(level) then
        return false
    end

    if self.waveLevel < level then
        return false
    end

    return true
end

function HeroFundData:getProCanGet(level)
    if self:getProGot(level) then
        return false
    end

    if not self.proBounght then
        return false
    end

    if self.waveLevel < level then
        return false
    end

    return true
end

function HeroFundData:getUtralCanGet(level)
    if self:getUtralGot(level) then
        return false
    end

    if not self.utralBounght then
        return false
    end

    if self.waveLevel < level then
        return false
    end

    return true
end

function HeroFundData:getHaveReward()
    if self.freeLevel < self.waveLevel then
        return true
    end

    if self.proBounght then
        if self.proLevel < self.waveLevel then
            return true
        end
    end

    if self.utralBounght then
        if self.utralLevel < self.waveLevel then
            return true
        end
    end

    return false
end

function HeroFundData:getReward(level, rewardType)
    local cfg = self:getConfig()[level]
    if not cfg then
        return
    end

    if rewardType == HeroFundData.REWARD_TYPE.FREE then
        return cfg.reward
    elseif rewardType == HeroFundData.REWARD_TYPE.PRO then
        return cfg.reward_pro
    elseif rewardType == HeroFundData.REWARD_TYPE.UTRAL then
        return cfg.reward_pro_max
    end
end

function HeroFundData:initTaskListener()
    local nowTime = Time:getServerTime()
    -- 活动结束就不用监听了
    if self.endTime > 0 and self.endTime < nowTime then
        ModuleManager.TaskManager:unRegisterAllModuleTask("HeroFundData")
        return false
    end

    ModuleManager.TaskManager:registerTask("HeroFundData", GConst.TaskConst.TASK_TYPE.X_BATTLE_PASS_WAVE, function(count)
        if not self:getIsOpen() then
            return
        end
        self:addWaveCount(count)
    end)
end

return HeroFundData