local GridCell = class("GridCell", BaseCell)

function GridCell:refresh(gridEntity, curElement, skillPosId)
    self:clearDoScale()
    self.gridEntity = gridEntity
    local uiMap = self:getUIMap()
    local downBg = uiMap["grid_cell.touch_node.ani_node.down_bg"]
    local elementType = gridEntity:getElementType()
    local elementIcon = uiMap["grid_cell.touch_node.ani_node.middle_bg"]
    if self.lastElementType ~= elementType then
        self.lastElementType = elementType
        local atlas, icon = ModuleManager.BattleManager:getElementIcon(elementType)
        elementIcon:setSprite(atlas, icon)
    end
    elementIcon:setVisible(not gridEntity:isElmentTypeInvalid())

    local showMask = false
    if curElement and (curElement ~= elementType or not gridEntity:canLink()) then
        showMask = true
    end
    self.curElement = curElement


    local obstacleObj = uiMap["grid_cell.touch_node.ani_node.obstacle"]
    obstacleObj:setVisible(gridEntity:isObstacleType())
    if self.lastObstacleIcon ~= gridEntity:getObstacleIcon() then
        self.lastObstacleIcon = gridEntity:getObstacleIcon()
        obstacleObj:setSprite(GConst.ATLAS_PATH.BATTLE, self.lastObstacleIcon)
    end

    if self.lastGridType ~= gridEntity:getGridType() then
        self.lastGridType = gridEntity:getGridType()
        local spineObj = uiMap["grid_cell.touch_node.ani_node.up_bg.ui_spine_obj"]
        local upBg = uiMap["grid_cell.touch_node.ani_node.up_bg"]
        self.spineAssetLoadOver = false
        if gridEntity:getSpineAsset() then
            local scale = gridEntity:getSpineScale()
            spineObj:setLocalScale(scale, scale, scale)
            spineObj:setActive(true)
            spineObj:loadAssetAsync(gridEntity:getSpineAsset(), function()
                self.spineAssetLoadOver = true
                local finalAniname = gridEntity:getSpineIdleName()
                if self.nextSpineAniName then
                    finalAniname = self.nextSpineAniName
                    self.nextSpineAniName = nil
                end
                if gridEntity:getSpineChangeName() then
                    spineObj:playAnimComplete(gridEntity:getSpineChangeName(), false, true, function()
                        spineObj:playAnim(finalAniname, true, false, true)
                    end, true)
                else
                    spineObj:playAnimComplete(finalAniname, true, true, nil, true)
                end
            end)
            upBg:setSprite(GConst.ATLAS_PATH.COMMON, "common_alpha")
        else
            spineObj:setActive(false)
            local atlas, icon = gridEntity:getIcon()
            upBg:setSprite(atlas, icon)
        end
    end

    local skillIcon = uiMap["grid_cell.touch_node.ani_node.skill_icon"]
    local skillId = gridEntity:getSkillId()
    if skillId then
        elementIcon:setVisible(false)
        skillIcon:setVisible(true)

        local sprite
        local skillEntity = self:getSkillEntity()
        if skillEntity then
            sprite = skillEntity:getBattleIcon()
        else
            local cfg = ModuleManager.BattleManager.SKILL_CFG[skillId]
            if cfg then
                sprite = tostring(cfg.battle_icon)
            end
        end

        if sprite and self.lastSkillSprite ~= sprite then
            self.lastSkillSprite = sprite
            skillIcon:setSprite(GConst.ATLAS_PATH.ICON_SKILL, self.lastSkillSprite)
        end

        if skillPosId and skillPosId ~= gridEntity:getPosId() then
            showMask = true
        else
            elementType = gridEntity:getElementType(skillEntity)
            if not elementType then
                showMask = false
            end
        end

        if skillEntity then
            local ignoreElementType = skillEntity:getIgnoreElementType()
            local skillBg
            if ignoreElementType and not self.lastShowHlElementType then
                skillBg = GConst.BattleConst.SKILL_ELEMENT_BG_2.skill
            else
                local mainElementType = self.lastShowHlElementType or skillEntity:getPosition()
                skillBg = GConst.BattleConst.SKILL_ELEMENT_BG_2[mainElementType]
            end
            if self.lastSkillBg ~= skillBg then
                self.lastSkillBg = skillBg
                downBg:setSprite(GConst.ATLAS_PATH.BATTLE, self.lastSkillBg)
            end
        end
    else
        skillIcon:setVisible(false)
    end

    self:showMask(showMask)
    self:showCircle(gridEntity:getNeedElimination())
    if self.gridEntity:getIsIdle() then
        self.lastShowHlElementType = nil
        self:hideAni()
    end
    self:showHighLight(false, self.lastShowHlElementType)

    if self.lastPosId ~= gridEntity:getPosId() then
        self.lastPosId = gridEntity:getPosId()
        self:getGameObject().name = "grid_cell_" .. self.lastPosId
    end

    self:setCountStr(GConst.EMPTY_STRING)
end

function GridCell:setCountStr(countStr)
    local uiMap = self:getUIMap()
    self.curCountStr = countStr
    uiMap["grid_cell.touch_node.ani_node.count"]:setText(countStr)
end

function GridCell:getCountStr()
    return self.curCountStr or GConst.EMPTY_STRING
end

function GridCell:showMask(showMask)
    local uiMap = self:getUIMap()
    uiMap["grid_cell.touch_node.ani_node.mask"]:setVisible(showMask)
end

function GridCell:addTouchListener(func)
    local uiMap = self:getUIMap()
    uiMap["grid_cell.touch_node"]:getComponent(GConst.TYPEOF_UNITY_CLASS.BF_ELIMINATION_TOUCH_EVENT):AddTouchEventListener(func)
end

function GridCell:showCircle(show)
    local uiMap = self:getUIMap()
    uiMap["grid_cell.touch_node.ani_node.circle"]:setVisible(show == true)
end

function GridCell:showHighLight(show, mainElementType)
    if not self.gridEntity then
        return
    end

    local uiMap = self:getUIMap()
    local downBg = uiMap["grid_cell.touch_node.ani_node.down_bg"]

    local skillId = self.gridEntity:getSkillId()
    downBg:setVisible(skillId ~= nil)
    if skillId then
        show = true -- 有技能，强制显示特效
        local skillEntity = self:getSkillEntity()
        local ignoreElementType = skillEntity:getIgnoreElementType()
        local skillBg
        if ignoreElementType and not mainElementType then
            skillBg = GConst.BattleConst.SKILL_ELEMENT_BG_2.skill
        else
            mainElementType = mainElementType or skillEntity:getPosition()
            skillBg = GConst.BattleConst.SKILL_ELEMENT_BG_2[mainElementType]
        end
        if self.lastSkillBg ~= skillBg then
            self.lastSkillBg = skillBg
            downBg:setSprite(GConst.ATLAS_PATH.BATTLE, self.lastSkillBg)
        end
    end


    local elementType = mainElementType or self.gridEntity:getElementType()
    if not self.outLineSfxObjs then
        self.outLineSfxObjs = {}
        for elementType, name in pairs(GConst.BattleConst.OUTLINE_SFX) do
            self.outLineSfxObjs[elementType] = uiMap["grid_cell.touch_node.ani_node.effect_node." .. name]
        end
    end

    local find = false
    for type, obj in pairs(self.outLineSfxObjs) do
        if show and not find then
            if skillId then
                if type == "skill" then
                    find = true
                end
            elseif elementType == type then
                find = true
            end
            if find then
                if self.lastShowHlElementType ~= type then
                    self.lastShowHlElementType = type
                end
            end
            obj:setActive(find)
        else
            obj:setActive(false)
        end
    end
    if not find then
        self.lastShowHlElementType = nil
    end
end

function GridCell:hideSkillSfx()
    if self.outLineSfxObjs and self.outLineSfxObjs.skill then
        self.outLineSfxObjs.skill:setActive(false)
    end
end

function GridCell:resetTranform()
    local uiMap = self:getUIMap()
    self.baseObject:setLocalScale(1, 1, 1)
    uiMap["grid_cell.touch_node.ani_node"]:setAnchoredPosition(0, 0)
    uiMap["grid_cell.touch_node.ani_node"]:setLocalScale(1, 1, 1)
end

function GridCell:showAni()
    local uiMap = self:getUIMap()
    if not self.aniComp then
        self.aniComp = uiMap["grid_cell.touch_node.ani_node"]:getComponent(GConst.TYPEOF_UNITY_CLASS.ANIMATOR)
    end
    -- CS.UnityEngine.Animator.StringToHash("idle") 结果是-601574123
    self.aniComp.enabled = true
    self.aniComp:Play(-601574123, -1, 0)
end

function GridCell:hideAni()
    self:clearDoScale()
    local uiMap = self:getUIMap()
    if not self.aniComp then
        self.aniComp = uiMap["grid_cell.touch_node.ani_node"]:getComponent(GConst.TYPEOF_UNITY_CLASS.ANIMATOR)
    end
    self.aniComp.enabled = false
    self:resetTranform()
end

function GridCell:doScale(targetScale, time, callback)
    self:clearDoScale()
    self.doScaleCallback = callback
    self.doScaleSeq = self.baseObject:createBindTweenSequence()
    self.doScaleSeq:Append(self.baseObject:getTransform():DOScale(targetScale, time))
    self.doScaleSeq:AppendCallback(function()
        self:clearDoScale()
    end)
end

function GridCell:clearDoScale()
    local callback = self.doScaleCallback
    self.doScaleCallback = nil
    if callback then
        callback()
    end
    if self.doScaleSeq then
        self.doScaleSeq:Kill()
        self.doScaleSeq = nil
    end
end

function GridCell:setOrder(uiOder)
    local uiMap = self:getUIMap()
    for elementType, name in pairs(GConst.BattleConst.OUTLINE_SFX) do
        local obj = uiMap["grid_cell.touch_node.ani_node.effect_node." .. name]
        obj:getComponent(GConst.TYPEOF_UNITY_CLASS.BF_EFFECT_HELPER):SetSortingOrder(uiOder, GConst.UI_EFFECT_ORDER.LEVEL4 + 1)
        obj:setActive(false)
    end
    local skillEffect = uiMap["grid_cell.touch_node.ani_node.effect_node.sfx_piece_qizi_b06"]
    skillEffect:getComponent(GConst.TYPEOF_UNITY_CLASS.BF_EFFECT_HELPER):SetSortingOrder(uiOder, GConst.UI_EFFECT_ORDER.LEVEL4 + 1)
    skillEffect:setActive(false)
end

function GridCell:setGridTypeIcon(icon)
    local uiMap = self:getUIMap()
    uiMap["grid_cell.touch_node.ani_node.up_bg"]:setSprite(GConst.ATLAS_PATH.BATTLE, icon)
    uiMap["grid_cell.touch_node.ani_node.up_bg.ui_spine_obj"]:setActive(false)
end

function GridCell:playAnim(aniName, loop, forceRefresh, forceGetSG)
    if not self.spineAssetLoadOver then
        self.nextSpineAniName = aniName
        return
    end
    self.nextSpineAniName = nil

    local uiMap = self:getUIMap()
    local spineObj = uiMap["grid_cell.touch_node.ani_node.up_bg.ui_spine_obj"]
    spineObj:playAnim(aniName, loop, forceRefresh, forceGetSG)
end

function GridCell:getSkillEntity()
    if not self.gridEntity then
        return
    end
    local skillId = self.gridEntity:getSkillId()
    if skillId then
        local skillEntity = self.gridEntity:getBattleData():getSkillEntityBySkillId(skillId, self.gridEntity:getSkillSide())
        return skillEntity
    end
end

return GridCell