local CollectionData = class("CollectionData", BaseData)

function CollectionData:ctor()
    self.data.isDirty = false
end

function CollectionData:clear()
end

function CollectionData:init(data)
    data = data or GConst.EMPTY_TABLE

    if EDITOR_MODE then
        Logger.logHighlight("收集数据")
        Logger.printTable(data)
    end

    self.curLevel = data.level or 0
    self.curPoint = data.point or 0
    self.collectHero = data.Heroes or GConst.EMPTY_TABLE
    self.collectSkin = data.Skins or GConst.EMPTY_TABLE
end

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

function CollectionData:isOpen()
    if not ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.COLLECT, true) then
        return false
    end
    return true
end

-- 是否有红点
function CollectionData:hasRedPoint()
    if not self:isOpen() then
        return false
    end

    -- 可领点数
    if self:hasCanCollectPoint(GConst.CollectionConst.TYPE.HERO) then
        return true
    end
    if self:hasCanCollectPoint(GConst.CollectionConst.TYPE.SKIN) then
        return true
    end

    -- 可领奖励
    for id, data in pairs(self:getRewardList()) do
        if self:isMeetTargetPoint(id) and not self:isRewardReceived(id) then
            return true
        end
    end

    return false
end

-- 是否有可领取的收集值
function CollectionData:hasCanCollectPoint(type)
    for idx, data in pairs(self:getCollectList(type)) do
        if self:canCollectPoint(type, data.id) then
            return true
        end
    end
    return false
end

-- 获取当前收集值
function CollectionData:getCurCollectPoint()
    return self.curPoint
end

-- 获取当前已领取奖励图鉴等级
function CollectionData:getCurCollectLevel()
    return self.curLevel
end

-- 获取总收集值
function CollectionData:getTotalCollectPoint()
    local list = self:getRewardList()
    if not list or #list <= 0 then
        return 0
    end
    return list[#list].point
end

-- 获取收集目标列表
function CollectionData:getCollectList(type)
    if type == GConst.CollectionConst.TYPE.HERO then
        if self.heroList == nil then
            self.heroList = {}
            for id, data in pairs(ConfigManager:getConfig("hero")) do
                data.id = id
                table.insert(self.heroList, data)
            end
            table.sort(self.heroList, function(a, b)
                if a.qlt ~= b.qlt then
                    return a.qlt > b.qlt
                end
                return a.id > b.id
            end)
            -- Logger.printTable(self.heroList)
        end
        return self.heroList
    elseif type == GConst.CollectionConst.TYPE.SKIN then
        if self.skinList == nil then
            self.skinList = {}
            for id, data in pairs(ConfigManager:getConfig("skin")) do
                if data.qlt > 1 then
                    data.id = id
                    table.insert(self.skinList, data)
                end
            end
            table.sort(self.skinList, function(a, b)
                if a.qlt ~= b.qlt then
                    return a.qlt > b.qlt
                end
                return a.id > b.id
            end)
            -- Logger.printTable(self.skinList)
        end
        return self.skinList
    end
end

-- 获取收集奖励列表
function CollectionData:getRewardList()
    if self.cfgRewards == nil then
        self.cfgRewards = ConfigManager:getConfig("collection")
    end

    return self.cfgRewards
end

-- 获取当前收集点数所在档位id
function CollectionData:getCurTargetId()
    for id, data in pairs(self:getRewardList()) do
        local prog = self:getRewardTargetProgress(id)
        if prog >= 0 and prog < 1 then
            -- 在进度条范围内
            return id
        end
    end
    return nil
end

-- 获取奖励档位收集进度
function CollectionData:getRewardTargetProgress(id)
    local cur = self:getCurCollectPoint()
    local rangeMin = self:getTargetMinPoint(id)
    local rangeMax = self:getTargetMaxPoint(id)
    -- Logger.logHighlight(id.."档位范围:"..rangeMin.."->"..rangeMax)

    if cur >= rangeMax then
        -- 超过进度条
        return 1
    elseif cur < rangeMin then
        --低于进度条
        return -1
    elseif cur == rangeMin then
        -- 进度最低值
        return 0
    else
        -- 在进度条范围内
        return (cur - rangeMin) / (rangeMax - rangeMin)
    end
end

-- 获取当前可领奖or正在进行中的目标
function CollectionData:getCanGetOrCollectingTargetId()
    for id, data in pairs(self:getRewardList()) do
        if not self:isMeetTargetPoint(id) then
            return id
        end

        if not self:isRewardReceived(id) then
            return id
        end
    end
    return nil
end

-- 获取收集目标点数
function CollectionData:getTargetPoint(id)
    local targetPoint = self:getRewardList()[id].point
    local lastTarget = self:getLastTarget(id)
    if lastTarget then
        return targetPoint - lastTarget.point
    end
    return targetPoint
end

-- 获取基于目标收集点数的当前收集值
function CollectionData:getTargetOwnedPoint(id)
    local curPoint = self:getCurCollectPoint()
    local lastTarget = self:getLastTarget(id)
    if lastTarget then
        return curPoint - lastTarget.point
    end
    return curPoint
end

-- 是否可收集点数
function CollectionData:canCollectPoint(type, id)
    if type == GConst.CollectionConst.TYPE.HERO then
        -- 基础奖励值 * 升级可领取次数
        local heroEntity = DataManager.HeroData:getHeroById(id)
        if heroEntity then
            local curLevel = heroEntity:getLv()
            local collectedLevel = self.collectHero[heroEntity:getCfgId()]
            if collectedLevel == nil then
                collectedLevel = 0
            end

            if collectedLevel >= curLevel then
                return false
            end

            return true
        end
    elseif type == GConst.CollectionConst.TYPE.SKIN then
        if not DataManager.SkinData:isUnlock(id) then
            return false
        end
        if self.collectSkin[id] and self.collectSkin[id] > 0 then
            -- 已收集
            return false
        end

        return true
    end
end

-- 获取可领取收集值
function CollectionData:getCanCollectPoint(type, id)
    if type == GConst.CollectionConst.TYPE.HERO then
        -- 基础奖励值 * 升级可领取次数
        local result = 0
        local heroEntity = DataManager.HeroData:getHeroById(id)
        if self:canCollectPoint(type, id) then
            local curLevel = heroEntity:getLv()
            local collectedLevel = self.collectHero[heroEntity:getCfgId()]
            if collectedLevel == nil then
                collectedLevel = 0
            end
            result = (curLevel - collectedLevel) * heroEntity:getCollectionPoint()
        else
            result = heroEntity:getCollectionPoint()
        end

        return result
    elseif type == GConst.CollectionConst.TYPE.SKIN then
        local cfg = ConfigManager:getConfig("skin")[id]
        return cfg and cfg.skin_point or 0
    end
end

-- 奖励是否已领取
function CollectionData:isRewardReceived(id)
    return self.curLevel >= id
end

-- 是否满足奖励领取条件
function CollectionData:isMeetTargetPoint(id)
    return self.curPoint >= self:getRewardList()[id].point
end

-- 独有逻辑 -----------------------------------------------------------------------------------------------

-- 获取档位范围最低值
function CollectionData:getTargetMinPoint(id)
    local rangeMin = 0
    local curPoint = self:getRewardList()[id].point
    local lastTarget = self:getLastTarget(id)
    if lastTarget then
        rangeMin = curPoint - math.floor((curPoint - lastTarget.point) / 2)
    end
    return rangeMin
end

-- 获取档位范围最高值
function CollectionData:getTargetMaxPoint(id)
    local rangeMax = 0
    local curPoint = self:getRewardList()[id].point
    local nextTarget = self:getNextTarget(id)
    if nextTarget then
        rangeMax = curPoint + math.floor((nextTarget.point - curPoint) / 2)
    else
        rangeMax = curPoint
    end
    return rangeMax
end

-- 获取上一个低档位
function CollectionData:getLastTarget(targetId)
    local result = nil
    for id, data in pairs(self:getRewardList()) do
        if id == targetId then
            return result
        end
        result = data
    end
    return nil
end

-- 获取下一个高档位
function CollectionData:getNextTarget(targetId)
    local finded = false
    for id, data in pairs(self:getRewardList()) do
        if finded then
            return data
        end
        if id == targetId then
            finded = true
        end
    end
    return nil
end

-- 事件 -----------------------------------------------------------------------------------------------

-- 领取收集点数成功
function CollectionData:onGetedPointSuccess(type, id, point)
    if type == GConst.CollectionConst.TYPE.HERO then
        if not self.collectHero[id] then
            self.collectHero[id] = 0
        end
        self.collectHero[id] = DataManager.HeroData:getHeroById(id):getLv()
    elseif type == GConst.CollectionConst.TYPE.SKIN then
        self.collectSkin[id] = 1
    end
    self.curPoint = point
    self:setDirty()
end

-- 领取图鉴奖励成功
function CollectionData:onGetedPointRewardSuccess()
    self.curLevel = self.curLevel + 1
    self:setDirty()
end

return CollectionData