local BattleConst = require "app/module/battle/battle_const"
local BOARD_HELER = require "app/module/battle/helper/board_helper"
local BattleGridEffectHandle = {}

local GRID_EFFECT_TYPE = BattleConst.GRID_EFFECT_TYPE
local GRID_BREAK_CONDITION = BattleConst.GRID_BREAK_CONDITION

local function _directionElinination(entity, gridEntities, battleController, onlyCheck)
    local effectParams = entity:getEffectParams()
    if not effectParams then
        return
    end
    local direction = effectParams[1]
    local list = ModuleManager.BattleManager:getPosIdsByDirection(entity:getPosId(), direction, battleController.battleData:getRowCount())
    return true, list
end

local function _crossSpread(entity, gridEntities, battleController, onlyCheck)
    if onlyCheck then
        return
    end

    local ePodId = entity:getPosId()
    local tempList = BattleConst.UP_DOWN_LEFT_RIGHT[entity:getPosId()]
    if not tempList then
        return
    end

    local succ = false
    tempList = table.shuffle(GFunc.getTable(tempList))
    for _, posId in ipairs(tempList) do
        local gridEntity = gridEntities[posId]
        if gridEntity and gridEntity:isEmptyIdle() then
            if not BOARD_HELER:hasGridEdgeBetween(battleController, posId, ePodId) then
                if battleController.battleUI and entity:getEffectSfx() then
                    battleController.battleUI:showGridEffectSfx(posId, entity:getEffectSfx(), function()
                        battleController.battleData:setGridType(posId, entity:getGridType() or BattleConst.GRID_TYPE.JELLY)
                    end)
                else
                    battleController.battleData:setGridType(posId, entity:getGridType() or BattleConst.GRID_TYPE.JELLY)
                end
                succ = true
                break
            end
        end
    end

    return succ
end

local function _crossSpreadNotBreak(entity, gridEntities, battleController, onlyCheck)
    if onlyCheck then
        return
    end

    if battleController.lastRoundBreakedGridType[entity:getGridType()] then
        return
    end

    local ePodId = entity:getPosId()
    local tempList = BattleConst.UP_DOWN_LEFT_RIGHT[entity:getPosId()]
    if not tempList then
        return
    end

    local succ = false
    tempList = table.shuffle(GFunc.getTable(tempList))
    for _, posId in ipairs(tempList) do
        local gridEntity = gridEntities[posId]
        if gridEntity and gridEntity:isEmptyIdle() then
            if not BOARD_HELER:hasGridEdgeBetween(battleController, posId, ePodId) then
                battleController.battleData:setGridType(posId, entity:getGridType() or BattleConst.GRID_TYPE.JELLY, true)
                if battleController.battleUI and entity:getEffectSfx() then
                    battleController.battleUI:showGridEffectSfx(posId, entity:getEffectSfx(), function()
                        battleController.battleData:setGridDirty(posId)
                    end)
                end
                succ = true
                break
            end
        end
    end

    return succ
end

local function _selectCommonSkill(entity, gridEntities, battleController, onlyCheck)
    if onlyCheck then
        return
    end
    battleController:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.SKILL_BOX_OPEN, 1)
    battleController.battleData:addCommonSelectSkillCount()
    return true
end

local function _rewardBox(entity, gridEntities, battleController, onlyCheck)
    if onlyCheck then
        return
    end
    battleController:onGotMysteryBoxIndexs()
    return true
end

local function _crossMoveNotBreak(entity, gridEntities, battleController, onlyCheck)
    if onlyCheck then
        return
    end

    if battleController.lastRoundBreakedGridType[entity:getGridType()] then
        return
    end

    -- 计算所有的蛇
    local allSnake = {}
    for posId, entity in pairs(gridEntities) do
        if entity:getEffectType() == BattleConst.GRID_EFFECT_TYPE.CROSS_MOVE_NOT_BREAK then
            table.insert(allSnake, entity)
        end
    end

    if not allSnake[1] then
        return
    end

    local map = {}
    local succ = false
    for _, entity in ipairs(allSnake) do
        local ePodId = entity:getPosId()
        local tempList = BattleConst.UP_DOWN_LEFT_RIGHT[entity:getPosId()]
        if tempList then
            tempList = table.shuffle(GFunc.getTable(tempList))
            for _, posId in ipairs(tempList) do
                local gridEntity = gridEntities[posId]
                if gridEntity and gridEntity:isEmptyIdle() and not map[posId] then
                    if not BOARD_HELER:hasGridEdgeBetween(battleController, posId, ePodId) then
                        local direction = ModuleManager.BattleManager:getPosDirection(entity:getPosId(), posId)
                        local cell = entity:getCell()
                        if cell then
                            if direction == BattleConst.BOARD_RANGE_TYPE.UP then
                                cell:playAnim("up", true, false, false)
                            elseif direction == BattleConst.BOARD_RANGE_TYPE.DOWN then
                                cell:playAnim("down", true, false, false)
                            elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT then
                                cell:playAnim("left", true, false, false)
                            elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT then
                                cell:playAnim("right", true, false, false)
                            end
                        end
                        map[entity:getPosId()] = entity
                        map[posId] = gridEntity
                        battleController.battleData:exchangeGridEntities(entity:getPosId(), posId)
                        succ = true
                        break
                    end
                end
            end
        end
    end
    if succ then
        battleController.battleUI:moveGridCells(map, function()
            for _, entity in ipairs(allSnake) do
                if entity:getCell() then
                    entity:getCell():playAnim(entity:getSpineIdleName(), true, false, false)
                end
            end
        end)
    end
    return succ
end

BattleGridEffectHandle._gridEffectOn = {
    [GRID_EFFECT_TYPE.DIRECTION_ELIMINATION] = _directionElinination,
    [GRID_EFFECT_TYPE.CROSS_SPREAD] = _crossSpread,
    [GRID_EFFECT_TYPE.SELECT_COMMON_SKILL] = _selectCommonSkill,
    [GRID_EFFECT_TYPE.REWARD_BOX] = _rewardBox,
    [GRID_EFFECT_TYPE.CROSS_SPREAD_NOT_BREAK] = _crossSpreadNotBreak,
    [GRID_EFFECT_TYPE.CROSS_MOVE_NOT_BREAK] = _crossMoveNotBreak,
}

function BattleGridEffectHandle.gridEffectOn(posId, gridEntities, triggerType, battleController, onlyCheck)
    local entity = gridEntities[posId]
    local effectType = entity:getEffectType()
    if not effectType then
        return
    end
    if entity:getEffectTrigger() ~= triggerType then
        return
    end

    local func = BattleGridEffectHandle._gridEffectOn[effectType]
    if func then
        return func(entity, gridEntities, battleController, onlyCheck)
    end
end

return BattleGridEffectHandle