local ArenaBountyData = class("ArenaBountyData", BaseData)

local ACT_GIFT_ID_BOUNTY = 80102
local ACT_GIFT_ID_BOUNTY_ADVANCED = 80202

function ArenaBountyData:ctor()
    self.data.dirty = false
end

function ArenaBountyData:clear()
    DataManager:unregisterCrossDayFunc("ArenaBountyData")
end

function ArenaBountyData:init(data)
    if EDITOR_MODE then
        Logger.logHighlight("竞技场战令初始化")
        Logger.printTable(data)
    end
    data = data or GConst.EMPTY_TABLE
    self.season = data.season or 1
    self.level = data.level or 1
    self.exp = data.exp or 0
    self.bought = data.bought
    self.isBoughtBase = nil
    self.isBoughtAdvance = nil
    self.popBoughtTime = LocalData:getArenaBountyPopTime()
    self.claimed = data.claimed or {}
    self.claimedCount = 0
    for k, v in pairs(self.claimed) do
        if v then
            self.claimedCount = self.claimedCount + 1
        end
    end
    self.proClaimed = data.pro_claimed or {}
    self.proClaimedCount = 0
    for k, v in pairs(self.proClaimed) do
        if v then
            self.proClaimedCount = self.proClaimedCount + 1
        end
    end
    self.endTime = 0
    self:initBountyTime()
    self:initBountyLevelCfg()
    DataManager:registerCrossDayFunc("ArenaBountyData", function()
		self:checkNextSeason()
		self:markDirty()
    end)
end

function ArenaBountyData:initBountyTime()
    local info = ConfigManager:getConfig("arena_time")[self.season]
    if info == nil then
        self.endTime = 0
        return
    end
    self.endTime = Time:getCertainTimeByStr(info.end_time)
end

function ArenaBountyData:initBountyLevelCfg()
    if self.bountyLevelCfg == nil then
        self.bountyLevelCfg = {}
    else
        for i = 1, #self.bountyLevelCfg do
            table.remove(self.bountyLevelCfg)
        end
    end
    if self.proRewards then
        for i = 1, #self.proRewards do
            table.remove(self.proRewards)
        end
    end
    local cfg = ConfigManager:getConfig("arena_bounty_level")
    for k, v in pairs(cfg) do
        if v.season == self.season then
            self.bountyLevelCfg[k % 100] = v
        end
    end
    self.repeatLevelInfo = table.remove(self.bountyLevelCfg)
end

function ArenaBountyData:checkNextSeason()
    if self.endTime > Time:getServerTime() then
        return
    end
    local nextSeason = self.season + 1
    local info = ConfigManager:getConfig("arena_time")[nextSeason]
    if info == nil then
        self.endTime = 0
        return
    end
    self.endTime = Time:getCertainTimeByStr(info.end_time)
    self.season = nextSeason
    self.level = 1
    self.exp = 0
    self.bought = false
    self.isBoughtBase = nil
    self.isBoughtAdvance = nil
    for k, v in pairs(self.claimed) do
        self.claimed[k] = false
    end
    self.claimedCount = 0
    for k, v in pairs(self.proClaimed) do
        self.proClaimed[k] = false
    end
    self.proClaimedCount = 0
    self:initBountyLevelCfg()
end

function ArenaBountyData:getBought()
    return self.bought
end

function ArenaBountyData:setBought(season, level)
    if self.season ~= season then
        return
    end
    self.bought = true
    self.isBoughtBase = nil
    self.isBoughtAdvance = nil
    level = level or self.level
    if self.level ~= level then
        self.level = level
        BIReport:postArenaBountyLevelUp(self:getBountyReportType(), self.level, self.exp, self.season)
    end
    DataManager.DailyTaskData:unlockBountyTask()
    self:markDirty()
end

function ArenaBountyData:getLevel()
    return self.level
end

function ArenaBountyData:getExp()
    return self.exp
end

function ArenaBountyData:addExp(num)
    self.exp = self.exp + num
    local levelBefore = self.level
    while true do
        local lvUpExp = self:getLvUpExp()
        if self.exp >= lvUpExp then
            self.exp = self.exp - lvUpExp
            self.level = self.level + 1
        else
            break
        end
    end
    if levelBefore ~= self.level then
        BIReport:postArenaBountyLevelUp(self:getBountyReportType(), self.level, self.exp, self.season)
    end
    self:markDirty()
end

function ArenaBountyData:getLvUpExp()
    local info = self:getSeasonInfoByLevel(self.level + 1)
    if info == nil then
        return self.repeatLevelInfo and self.repeatLevelInfo.exp or 1
    end
    return info.exp
end

function ArenaBountyData:getRepeatLevelInfo()
    return self.repeatLevelInfo
end

function ArenaBountyData:getIsOpen()
    if ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.ARENA, true) and self.endTime > Time:getServerTime() then
        return true
    end
    return false
end

function ArenaBountyData:getBannerName()
    return ConfigManager:getConfig("arena_time")[self.season].ui_banner
end

function ArenaBountyData:getRewardBannerName()
    return "bounty_btn_main_0"
end

function ArenaBountyData:getSeason()
    return self.season
end

function ArenaBountyData:getSeasonInfoByLevel(lv)
    return self.bountyLevelCfg[lv]
end

function ArenaBountyData:getMaxLevel()
    return #self.bountyLevelCfg
end

function ArenaBountyData:getAllProRewards()
    if self.proRewards and #self.proRewards > 0 then
        return self.proRewards
    end
    local rewards = {}
	for i = 1, #self.bountyLevelCfg do
		local cfg = self.bountyLevelCfg[i]
		if cfg.reward_pro then
		    table.insert(rewards, cfg.reward_pro)
        end
	end
	self.proRewards = GFunc.mergeRewards(rewards)
    local cfg = ConfigManager:getConfig("item")
	table.sort(self.proRewards, function(a, b)
        if cfg[a.id].type == cfg[b.id].type then
            return a.id > b.id
        else
            return cfg[a.id].type > cfg[b.id].type
        end
	end)
	return self.proRewards
end

function ArenaBountyData:getLevelState(lv)
    return self.claimed[lv]
end

function ArenaBountyData:getProLevelState(lv)
    return self.proClaimed[lv]
end

function ArenaBountyData:getIfCanBuyLevel()
    local maxLevel = self:getMaxLevel()
    if maxLevel > 0 and self.level < maxLevel then
        return true
    end
    return false
end

-- 未领取的最小奖励的index
function ArenaBountyData:getMinUnclaimedRewardIndex()
    local level = self.level
    local maxLevel = self:getMaxLevel()
    if level > maxLevel then
        level = maxLevel
    end
    if self.claimedCount < self.level then
        for i = 1, level do
            if not self.claimed[i] then
                return i
            end
        end
    end
    if self.bought and self.proClaimedCount < self:getMaxLevel() then
        for i = 1, level do
            if not self.proClaimed[i] then
                return i
            end
        end
    end
    return level
end

-- 是否有未领取的奖励
function ArenaBountyData:getIfCanClaimReward()
    if not self:getIsOpen() then
        return false
    end
    if self.claimedCount < self.level then
        return true
    end
    if self.bought and self.level <= self:getMaxLevel() and self.proClaimedCount < self.level then
        return true
    end
    return false
end

-- 展示一键领取按钮
function ArenaBountyData:canShowOneKeyGetBtn()
    local maxLevel = self:getMaxLevel()
    local curLevel = math.min(maxLevel, self.level)
    if curLevel <= 0 then
        return false
    end

    local count = self:getShowOneKeyLimit()
    for i = 1, curLevel do
        if not self.claimed[i] then
            count = count - 1
        end
        if self.bought and not self.proClaimed[i] then
            count = count - 1
        end
        if count <= 0 then
            return true
        end
    end

    return false
end

function ArenaBountyData:getShowOneKeyLimit()
    if not self.showOneKeyLimit then
        self.showOneKeyLimit = GFunc.getConstIntValue("bounty_click")
    end

    return self.showOneKeyLimit
end

function ArenaBountyData:onOneKeyClaimReward()
    local maxLevel = self:getMaxLevel()
    local curLevel = math.min(maxLevel, self.level)
    if curLevel <= 0 then
        return false
    end
    for i = 1, curLevel do
        if not self.claimed[i] then
            self.claimed[i] = true
            self.claimedCount = self.claimedCount + 1
        end
        if self.bought and not self.proClaimed[i] then
            self.proClaimed[i] = true
            self.proClaimedCount = self.proClaimedCount + 1
        end
    end

    self:markDirty()
end

-- 是否可以领取重复奖励
function ArenaBountyData:getIfCanClaimRepeatReward()
    local maxLevel = self:getMaxLevel()
    if maxLevel <= 0 then
        return false
    end
    if self.level <= maxLevel then
        return false
    end
    return not self:getLevelState(self.level)
end

function ArenaBountyData:onClaimReward(level)
    if self.claimed[level] then
        return
    end
    local maxLevel = self:getMaxLevel()
    if level > maxLevel then
        for i = maxLevel, level do
            self.claimed[i] = true
            self.claimedCount = self.claimedCount + 1
        end
    else
        self.claimed[level] = true
        self.claimedCount = self.claimedCount + 1
    end

    self:markDirty()
end

function ArenaBountyData:onClaimProReward(level)
    if self.proClaimed[level] then
        return
    end
    self.proClaimed[level] = true
    self.proClaimedCount = self.proClaimedCount + 1
    self:markDirty()
end

function ArenaBountyData:getBuyBountyLevelCost()
    if self.buyBountyLevelCost == nil then
        self.buyBountyLevelCost = ConfigManager:getConfig("const")["arena_bounty_buy_cost"].reward
    end
    return self.buyBountyLevelCost
end

function ArenaBountyData:onBoughtLevel()
    self.level = self.level + 1
    BIReport:postArenaBountyLevelUp(self:getBountyReportType(), self.level, self.exp, self.season)
    self:markDirty()
end

function ArenaBountyData:getGiftId(advanced)
    if advanced then
        return ACT_GIFT_ID_BOUNTY_ADVANCED
    else
        return ACT_GIFT_ID_BOUNTY
    end
end

function ArenaBountyData:markDirty()
    self.data.dirty = not self.data.dirty
end

function ArenaBountyData:getEndTime()
    return self.endTime
end

function ArenaBountyData:getExpItemIcon()
    local id = GConst.ItemConst.ITEM_ID_ARENA_BOUNTY_EXP
    local info = ConfigManager:getConfig("item")[id]
    if info == nil then
        return GConst.EMPTY_STRING
    end
    return info.icon
end

function ArenaBountyData:getIsPopBought()
    if not self:getIsOpen() then
        return false
    end
    if self.bought then
        return false
    end
    return self.popBoughtTime < Time:getBeginningOfServerToday()
end

function ArenaBountyData:markPopBought()
    if self.popBoughtTime >= Time:getBeginningOfServerToday() then
		return
	end
	self.popBoughtTime = Time:getBeginningOfServerToday()
	LocalData:setArenaBountyPopTime(self.popBoughtTime)
end

function ArenaBountyData:clearPopBought()
    self.popBoughtTime = 0
end

function ArenaBountyData:getRechargeId(advanced)
    local cfg = ConfigManager:getConfig("act_gift")
    local id = self:getGiftId(advanced)
    if cfg[id] then
        return cfg[id].recharge_id
    end
    return 0
end

function ArenaBountyData:getBuyProBountyAddLevelCount()
    if self.buyProBountyAddLevelCount == nil then
        self.buyProBountyAddLevelCount = ConfigManager:getConfig("const")["arena_bounty_senior_rise"].value
    end
    return self.buyProBountyAddLevelCount
end

function ArenaBountyData:getIsBoughtBase()
    if self.isBoughtBase == nil then
        self.isBoughtBase = DataManager.ShopData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, ACT_GIFT_ID_BOUNTY) > 0
    end
	return self.isBoughtBase
end

function ArenaBountyData:getIsBoughtAdvance()
    if self.isBoughtAdvance == nil then
	    self.isBoughtAdvance = DataManager.ShopData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, ACT_GIFT_ID_BOUNTY_ADVANCED) > 0
    end
    return self.isBoughtAdvance
end

function ArenaBountyData:getBountyReportType()
    if not self.bought then
        return 0
    end
    if self:getIsBoughtBase() then
        return 1
    end
    if self:getIsBoughtAdvance() then
        return 2
    end
    return 0
end

return ArenaBountyData