local BattleGridEntity = class("BattleGridEntity", BaseData)
local BattleConst = GConst.BattleConst

local GRID_TYPE_CFG = ConfigManager:getConfig("grid_type")

function BattleGridEntity:ctor(data)
    self:clear()
    self.posId = data.posId or 0
    self.gridType = data.gridType or BattleConst.GRID_TYPE.EMPTY
    self.elementType = data.elementType or BattleConst.ELEMENT_TYPE.NONE
    self.skillId = data.skillId
    self.linkSkillCount = data.linkSkillCount or 0 -- 任意链接技能激活次数
    self.battleData = data.battleData
    self.isIdle = false
    self.breakCount = 0
    self.data.isDirty = false
    self:determineIdleStatus()
end

function BattleGridEntity:clear()
    self.gridType = BattleConst.GRID_TYPE.EMPTY
    self.elementType = BattleConst.ELEMENT_TYPE.RED
    self.skillId = nil
    self.linkSkillCount = 0 -- 任意链接技能激活次数
    self.isIdle = false
    self.breakCount = 0
    self.data.isDirty = false
end

function BattleGridEntity:getBattleData()
    return self.battleData
end

function BattleGridEntity:getSnapshoptInfo()
    return {
        posId = self.posId,
        gridType = self.gridType,
        elementType = self.elementType,
        isIdle = self.isIdle,
        skillId = self.skillId,
        linkSkillCount = self.linkSkillCount,
        breakCount = self.breakCount,
    }
end

function BattleGridEntity:setInfoBySnapshop(snapshot)
    self.posId = snapshot.posId or 0
    self.gridType = snapshot.gridType or BattleConst.GRID_TYPE.EMPTY
    self.elementType = snapshot.elementType or BattleConst.ELEMENT_TYPE.RED
    self.isIdle = snapshot.isIdle
    self.skillId = snapshot.skillId
    self.linkSkillCount = snapshot.linkSkillCount
    self.breakCount = snapshot.breakCount
    self:setDirty()
end

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

function BattleGridEntity:getPosId()
    return self.posId
end

function BattleGridEntity:setPosId(posId)
    self.posId = posId
end

function BattleGridEntity:getGridType()
    return self.gridType
end

function BattleGridEntity:getElementType(skillEntity)
    if skillEntity and skillEntity:getIgnoreElementType() and self.linkSkillCount <= 0 then
        return nil
    end

    return self.elementType
end

function BattleGridEntity:isCantFallType()
    return self:getGridTypeConfig().can_fall ~= 1
end

function BattleGridEntity:isObstacleType()
    return self.gridType == BattleConst.GRID_TYPE.OBSTACLE
end

function BattleGridEntity:isEmptyType()
    return self.gridType == BattleConst.GRID_TYPE.EMPTY
end

function BattleGridEntity:isElmentTypeInvalid()
    return self:getGridTypeConfig().element_invalid == 1
end

---- 返回值1为true， 返回值2为是否为idle状态；返回值1为false时，没有返回值2
function BattleGridEntity:tryBreakGrid(condition, onlyCheck)
    if self:getIsIdle() then
        if not onlyCheck then
            self:setGridType(BattleConst.GRID_TYPE.EMPTY)
        end
        return false
    end
    local nextGridType = self:getNextGridType()
    local isIdle = false
    if nextGridType then
        if not self:canBreakByThisCondition(condition) then
            return false
        end

        if not onlyCheck then
            self:addBreakCount(1)
            if self:getBreakCount() < self:getCfgBreakCount() then
                self:setDirty()
                return false
            end

            local breakStayElement = self:getBreakStayElement()
            self:setGridType(nextGridType)
            if nextGridType == BattleConst.GRID_TYPE.EMPTY and not breakStayElement then
                isIdle = true
            end
        else
            if self:getBreakCount() + 1 < self:getCfgBreakCount() then
                return false
            end

            local breakStayElement = self:getBreakStayElement()
            if nextGridType == BattleConst.GRID_TYPE.EMPTY and not breakStayElement then
                isIdle = true
            end
        end
    else
        if self:getSkillId() then
            if condition == BattleConst.GRID_BREAK_CONDITION.LINE then -- 技能破碎逻辑为，链接消除
                isIdle = true
            else
                return false
            end
        else
            if self:isEmptyIdle() and (condition == BattleConst.GRID_BREAK_CONDITION.LINE or condition == BattleConst.GRID_BREAK_CONDITION.SKILL) then -- 空类型/带技能破碎逻辑为，链接消除 置为闲置即消除
                isIdle = true
            else -- 不可破碎类型
                return false
            end
        end
    end
    if not onlyCheck then
        self:setIsIdle(isIdle)
        self:setDirty()
    end
    return true, isIdle
end

function BattleGridEntity:getPos()
    return ModuleManager.BattleManager:getPosInfo(self.posId, self.battleData:getRowCount())
end

function BattleGridEntity:setCell(cell)
    self.gridCell = cell
end

function BattleGridEntity:getCell()
    return self.gridCell
end

function BattleGridEntity:getIsIdle()
    return self.isIdle
end

function BattleGridEntity:setIsIdle(isIdle)
    self.isIdle = isIdle == true
end

function BattleGridEntity:canLink()
    if self:getIsIdle() then
        return false
    end
    return self:getGridTypeConfig().cant_link ~= 1
end

function BattleGridEntity:addPath(singlePath)
    self:getPath()
    table.insert(self.pathList, singlePath)
end

function BattleGridEntity:getPath()
    if not self.pathList then
        self.pathList = {}
    end
    return self.pathList
end

function BattleGridEntity:clearPath()
    self.pathList = {}
end

function BattleGridEntity:setGridType(gridType, noDirty)
    if self.gridType ~= gridType then
        self.gridType = gridType
        self.breakCount = 0
        if not noDirty then
            self:setDirty()
        end
    end
end

function BattleGridEntity:setElementType(elementType, noDirty)
    self.elementType = elementType
    if self.battleData:getCacheLockedElement(self.elementType) and not self.skillId then
        self:setGridType(BattleConst.GRID_TYPE.LOCK)
    end
    if not noDirty then
        self:setDirty()
    end
end

function BattleGridEntity:getSkillId()
    if not self.skillId or self.skillId <= 0 then
        return
    end
    return self.skillId
end

function BattleGridEntity:setSkilId(skillId, noDirty, side)
    self.skillId = skillId
    self.linkSkillCount = 0
    self.skillSide = side or GConst.BattleConst.SIDE_ATK
    if not noDirty then
        self:setDirty()
    end
end

function BattleGridEntity:getSkillSide()
    return self.skillSide
end

function BattleGridEntity:getSkillMatchType()
    if not self:getSkillId() then
        return
    end
    local skillEntity = self:getSkillEntity()
    return skillEntity and skillEntity:getPosition()
end

function BattleGridEntity:getSkillEntity()
    if not self:getSkillId() then
        return
    end
    local skillEntity = self.battleData:getSkillEntityBySkillId(self:getSkillId(), self.skillSide)
    return skillEntity
end


function BattleGridEntity:canChangeInfo()
    if self:canLink() and not self:getSkillId() then
        return true
    end
    return false
end

function BattleGridEntity:isEmptyIdle()
    if self:isEmptyType() and not self:getSkillId() and not self:getIsIdle() then
        return true
    end
    return false
end

function BattleGridEntity:isNotObstacleIdle()
    if not self:isObstacleType() and not self:getSkillId() and not self:getIsIdle() then
        return true
    end
    return false
end

function BattleGridEntity:isCanFallStatus()
    if not self:isCantFallType() and not self:getIsIdle() then
        return true
    end
    return false
end

function BattleGridEntity:isLock()
    return self.gridType == BattleConst.GRID_TYPE.LOCK
end

function BattleGridEntity:getNeedElimination()
    return self.needElimination
end

function BattleGridEntity:getNeedChangePos()
    if not self:getSkillId() then
        return false
    end

    local skillEntity = self:getSkillEntity()
    if not skillEntity then
        return false
    end
    if skillEntity:getMethond() == BattleConst.SKILL_METHOD_TYPE.ON_FINAL then
        return true
    end

    return false
end

function BattleGridEntity:addLinkSkillCount(count)
    self.linkSkillCount = self.linkSkillCount + (count or 1)
end

function BattleGridEntity:setLinkSkillCount(count)
    self.linkSkillCount = count or 0
end

function BattleGridEntity:getLinkSkillCount()
    return self.linkSkillCount
end

function BattleGridEntity:determineIdleStatus()
    if not self.isIdle and self.gridType == BattleConst.GRID_TYPE.EMPTY and self.elementType == BattleConst.ELEMENT_TYPE.NONE then
        self.isIdle = true
    end
end

function BattleGridEntity:getObstacleIcon()
    if not self.obstacleIcon then
        return "battle_hinder_1"
    end

    return self.obstacleIcon
end

function BattleGridEntity:setObstacleIcon(icon)
    self.obstacleIcon = icon
end

function BattleGridEntity:getGridTypeConfig()
    if not self.gridCfg or self.lastGridType ~= self.gridType then
        self.lastGridType = self.gridType
        self.gridCfg = GRID_TYPE_CFG[self.lastGridType]
        self.breakConditionMap = {}
        if self.gridCfg.break_condition then
            for _, condition in ipairs(self.gridCfg.break_condition) do
                self.breakConditionMap[condition] = true
            end
        end
    end

    return self.gridCfg
end

function BattleGridEntity:getNextGridType()
    return self:getGridTypeConfig().next_type
end

function BattleGridEntity:getIcon()
    local icon = self:getGridTypeConfig().icon
    if not icon then
        return GConst.ATLAS_PATH.COMMON, "common_alpha"
    end
    return GConst.ATLAS_PATH.BATTLE, icon
end

function BattleGridEntity:getBreakSfx()
    local sfxName = self:getGridTypeConfig().break_sfx
    if not sfxName then
        return
    end

    if not self.cacheBreakSfxPaths then
        self.cacheBreakSfxPaths = {}
    end
    if not self.cacheBreakSfxPaths[sfxName] then
        self.cacheBreakSfxPaths[sfxName] = "assets/prefabs/effects/battle/" .. sfxName .. ".prefab"
    end
    return self.cacheBreakSfxPaths[sfxName]
end

function BattleGridEntity:getBreakConditionMap()
    self:getGridTypeConfig()
    return self.breakConditionMap
end

function BattleGridEntity:canBreakByThisCondition(condition)
    self:getGridTypeConfig()
    if not self.breakConditionMap then
        return false
    end
    return self.breakConditionMap[condition] == true
end

function BattleGridEntity:getBreakStayElement()
    return self:getGridTypeConfig().break_stay_element == 1
end

function BattleGridEntity:getCfgBreakCount()
    return self:getGridTypeConfig().break_count or 0
end

function BattleGridEntity:getBreakCount()
    return self.breakCount
end

function BattleGridEntity:addBreakCount(count)
    self.breakCount = self.breakCount + count
end

function BattleGridEntity:getEffectType()
    return self:getGridTypeConfig().effect
end

function BattleGridEntity:getEffectParams()
    return self:getGridTypeConfig().effect_params
end

function BattleGridEntity:getEffectTrigger()
    return self:getGridTypeConfig().effect_trigger
end

function BattleGridEntity:getBreakFlyToCharacter()
    return self:getGridTypeConfig().break_fly_to_character == 1
end

function BattleGridEntity:getBreakFlyToCharacterIcon()
    return self:getGridTypeConfig().bftc_icon
end

function BattleGridEntity:getSpineAsset()
    return self:getGridTypeConfig().spine_name
end

function BattleGridEntity:getSpineIdleName()
    return self:getGridTypeConfig().spine_idle
end

function BattleGridEntity:getSpineChangeName()
    return self:getGridTypeConfig().spine_change
end

function BattleGridEntity:getSpineScale()
    return self:getGridTypeConfig().zoom or 1
end

function BattleGridEntity:getBftcTime()
    return self:getGridTypeConfig().bftc_time or 0
end

function BattleGridEntity:getCantUpset()
    return self:getGridTypeConfig().cant_upset == 1
end

function BattleGridEntity:getEffectSfx()
    local sfxName = self:getGridTypeConfig().effect_sfx
    if not sfxName then
        return
    end

    if not self.cacheEffectSfxPaths then
        self.cacheEffectSfxPaths = {}
    end
    if not self.cacheEffectSfxPaths[sfxName] then
        self.cacheEffectSfxPaths[sfxName] = "assets/prefabs/effects/battle/" .. sfxName .. ".prefab"
    end
    return self.cacheEffectSfxPaths[sfxName]
end

function BattleGridEntity:getEffectSfxFlow()
    return self:getGridTypeConfig().sfx_flow
end

return BattleGridEntity