local EquipEntity = class("EquipEntity", BaseData)
local DEFAULT_FACTOR = GConst.BattleConst.DEFAULT_FACTOR

function EquipEntity:ctor(heroId, part, level)
	self.level = level or 0

    self.heroEntity = nil
    self.cfg, self.cfgId = table.find(ConfigManager:getConfig("equip"), function(value)
        return value.hero == heroId and value.part == part
    end)
end

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

-- 获取部位id
function EquipEntity:getId()
    return self.cfgId
end

-- 获取部位所属英雄
function EquipEntity:getHeroId()
    return self.cfg.hero
end

-- 获取部位类型
function EquipEntity:getPart()
    return self.cfg.part
end

-- 获取部位基础生命值
function EquipEntity:getBaseHp()
    if self.cfg.armor_hp and self.cfg.armor_hp[self.level] then
        return self.cfg.armor_hp[self.level]
    end
    return 0
end

-- 获取部位加成后生命值
function EquipEntity:getHp()
    local result = self:getBaseHp()
    result = result + self:getHeroEntity():getTotalBaseHp() * self:getHpPercent() // DEFAULT_FACTOR
    return result
end

-- 获取部位基础攻击力
function EquipEntity:getBaseAttack()
    if self.cfg.armor_atk and self.cfg.armor_atk[self.level] then
        return self.cfg.armor_atk[self.level]
    end
    return 0
end

-- 获取部位加成后攻击力
function EquipEntity:getAttack()
    local result = self:getBaseAttack()
    result = result + self:getHeroEntity():getTotalBaseAtk() * self:getAtkPercent() // DEFAULT_FACTOR
    return result
end

-- 获取部位普攻伤害
function EquipEntity:getNormalHurt()
    if self.cfg.normal_hurt_add and self.cfg.normal_hurt_add[self.level] then
        return self.cfg.normal_hurt_add[self.level]
    end
    return 0
end

-- 获取部位技能伤害
function EquipEntity:getSkillHurt()
    if self.cfg.skill_hurt_add and self.cfg.skill_hurt_add[self.level] then
        return self.cfg.skill_hurt_add[self.level]
    end
    return 0
end

-- 获取攻击加成百分比
function EquipEntity:getAtkPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_ATTACK_ADD_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

-- 获取生命值加成百分比
function EquipEntity:getHpPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_HP_ADD_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

-- 获取暴击率百分比
function EquipEntity:getCritPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_CRIT_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

--获取暴击伤害百分比
function EquipEntity:getCritHurtPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_CRIT_TIME_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

-- 获取治疗百分比
function EquipEntity:getHealPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_CURED_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

-- 获取普攻增伤百分比
function EquipEntity:getNormalHurtPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_NORMAL_HURTP_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

-- 获取技能增伤百分比
function EquipEntity:getSkillHurtPercent()
    local attrs = self:getStageAttr()
    if not attrs or #attrs == 0 then
        return 0
    end

    local num = 0
    for index, attr in ipairs(attrs) do
        if table.containValue(GConst.MATCH_SKILL_HURTP_NAME, attr.type) then
            num = num + attr.num
        end
    end
    return num
end

-- 获取部位阶段等级，未达到最低阶段等级时，阶段为0
function EquipEntity:getStage()
    local stage = 0
    for idx, level in pairs(self.cfg.features_level) do
        if self.level < level then
            break
        end
        stage = idx
    end
    return stage
end

-- 获取属性描述
function EquipEntity:getAttrDesc()
    local stage = self:getStage()
    if self:getPart() ~= GConst.EquipConst.PART_TYPE.WEAPON then
        stage = DataManager.EquipData:getMinArmorStage(self:getHeroId())
    end

    local strAttr = ""
    for i = 1, stage + 1 do
        if i > #self.cfg.features_level or i > #self.cfg.features_attr then
            break
        end

        local level = self.cfg.features_level[i]
        local attr = self.cfg.features_attr[i]
        local str = I18N:getGlobalText(I18N.GlobalConst.EQUIP_DESC_3) .. level .. ":".. GFunc.getAttrDesc(attr.type, attr.num)
        if self:getPart() ~= GConst.EquipConst.PART_TYPE.WEAPON then
            str = I18N:getGlobalText(I18N.GlobalConst.EQUIP_DESC_26, level) .. GFunc.getAttrDesc(attr.type, attr.num)
        end
        if i < stage + 1 then
            strAttr = "<color=#EEDFFF>" .. strAttr.. str .. "\n</color>"
        else
            strAttr = "<color=#9C94BE>" .. strAttr.. str .. "(" .. I18N:getGlobalText(I18N.GlobalConst.EQUIP_DESC_12) .. ")</color>"
        end
    end

    return strAttr
end

-- 获取部位已获得属性
function EquipEntity:getStageAttr()
    local stage = self:getStage()
    if self:getPart() ~= GConst.EquipConst.PART_TYPE.WEAPON then
        stage = DataManager.EquipData:getMinArmorStage(self:getHeroId())
    end

    if self.curAttr == nil or #self.curAttr ~= stage then
        self.curAttr = {}
        for i = 1, stage do
            table.insert(self.curAttr, self.cfg.features_attr[i])
        end
    end

    return self.curAttr
end

-- 获取部位图标id
function EquipEntity:getIconId()
    local stage = self:getStage()
    if stage then
        return self.cfg.weapon_icon[stage + 1]
    end
    return nil
end

-- 获取部位名称
function EquipEntity:getName()
    local names = I18N:getText("equip", self:getId(), "name")
    names = string.split(names, ",")
    return names[self:getStage() + 1] or ""
end

-- 获取部位当前等级
function EquipEntity:getLevel()
    return self.level
end

-- 获取部位等级上限
function EquipEntity:getMaxLevel()
    if self:getPart() == GConst.EquipConst.PART_TYPE.WEAPON then
        -- 武器等级上限是玩家等级*2
        return DataManager.PlayerData:getLv() * 2
    else
        -- 防具等级上限是当前英雄武器等级
        return DataManager.EquipData:getEquip(self:getHeroId(), GConst.EquipConst.PART_TYPE.WEAPON):getLevel()
    end
end

-- 部位是否可升级
function EquipEntity:canLevelUp()
    -- 判断英雄解锁
    if not self:getHeroEntity():isActived() then
        return false
    end

    --判断材料
    if not self:isEnoughMaterial() then
        return false
    end

    -- 判断金币
    if not self:isEnoughGold() then
        return false
    end

    -- 判断等级
    if self:isMaxLevel() then
        return false
    end

    return true
end

-- 升级材料是否满足
function EquipEntity:isEnoughMaterial()
    for index, cost in ipairs(self:getUpgradeMaterials()) do
        if cost.num > DataManager.BagData.ItemData:getItemNumById(cost.id) then
            return false
        end
    end
    return true
end

-- 升级金币是否满足
function EquipEntity:isEnoughGold()
    return DataManager.BagData.ItemData:getItemNumById(GConst.ItemConst.ITEM_ID_GOLD) >= self:getUpgradeGoldNum()
end

-- 部位是否是最大等级
function EquipEntity:isMaxLevel()
    return self:getLevel() >= self:getMaxLevel()
end

-- 获取部位上一等级实例
function EquipEntity:getLastLevelEntity()
    if self:getLevel() == 0 then
        return nil
    end
    return DataManager.EquipData:createEntity(self:getHeroId(), self:getPart(), self:getLevel() - 1)
end

-- 获取部位下一等级实例
function EquipEntity:getNextLevelEntity()
    return DataManager.EquipData:createEntity(self:getHeroId(), self:getPart(), self:getLevel() + 1)
end

-- 获取部位升级所需材料和金币
function EquipEntity:getUpgradeCost()
    local nextCost = ConfigManager:getConfig("equip_level")[self:getLevel() + 1]
    if not nextCost then
        return
    end

    local part = self:getPart()
    if part == GConst.EquipConst.PART_TYPE.WEAPON then
        return nextCost.weapon_cost
    elseif part == GConst.EquipConst.PART_TYPE.HAT then
        return nextCost.hat_cost
    elseif part == GConst.EquipConst.PART_TYPE.CLOTHES then
        return nextCost.clothes_cost
    elseif part == GConst.EquipConst.PART_TYPE.BELT then
        return nextCost.belt_cost
    elseif part == GConst.EquipConst.PART_TYPE.HANDGUARD then
        return nextCost.handguard_cost
    end
end

-- 获取部位升级所需金币数
function EquipEntity:getUpgradeGoldNum()
    local cost = self:getUpgradeCost()
    if cost then
        for key, value in pairs(cost) do
            if GFunc.getRewardId(value) == GConst.ItemConst.ITEM_ID_GOLD then
                return GFunc.getRewardNum(value)
            end
        end
    end
    return 0
end

-- 获取部位升级所需材料
function EquipEntity:getUpgradeMaterials()
    local cost = self:getUpgradeCost()
    local materials = {}
    if cost then
        for key, value in pairs(cost) do
            if GFunc.getRewardId(value) ~= GConst.ItemConst.ITEM_ID_GOLD then
                table.insert(materials, value)
            end
        end
    end
    return materials
end

-- 升级
function EquipEntity:onLevelUp()
    self.level = self.level + 1

    -- 检查是否升段
    local lastEntity = DataManager.EquipData:getEquip(self:getHeroId(), self:getPart(), self.level - 1)
    if lastEntity:getStage() < self:getStage() then
        EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.EQUIP_UPSECTION_SUCCESS, self:getPart())
    else
        EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.EQUIP_UPGRADE_SUCCESS, self:getPart())
    end
    self:setDirty()
end

function EquipEntity:setHeroEntity(heroEntity)
    self.heroEntity = heroEntity
end

function EquipEntity:getHeroEntity()
    if self.heroEntity then
        return self.heroEntity
    end

    return DataManager.HeroData:getHeroById(self:getHeroId())
end

return EquipEntity