local BattleConst = GConst.BattleConst
local BattleInstructionsHelper = {}

BattleInstructionsHelper._generateAttackInstructions = function(instructions, skillEntity, elementType, elementTypeCount)
    if skillEntity then
        if elementType == skillEntity:getPosition() then
            table.insert(instructions, {
                name = BattleConst.INSTRUCTION_NAME.PLAY_SKILL,
                skillMatch = elementType,
                count = elementTypeCount,
            })
        else
            if skillEntity:getEffect() ~= nil then
                table.insert(instructions, {
                    name = BattleConst.INSTRUCTION_NAME.PLAY_SKILL,
                    skillMatch = skillEntity:getPosition(),
                    count = 0,
                })
            end
            if elementTypeCount > 0 then
                table.insert(instructions, {
                    name = BattleConst.INSTRUCTION_NAME.GENERAL_ATTACK,
                    skillMatch = elementType,
                    count = elementTypeCount,
                })
            end
        end
    else
        ---- 普攻
        if elementTypeCount > 0 then
            table.insert(instructions, {
                name = BattleConst.INSTRUCTION_NAME.GENERAL_ATTACK,
                skillMatch = elementType,
                count = elementTypeCount,
            })
        end
    end

    -- if assistingList then
    --     table.insert(self.instructions, {
    --         name = BattleConst.INSTRUCTION_NAME.ASSISTING,
    --         assistingList = assistingList,
    --     })
    -- end
end

local generateEliminateEffects = function(instructions, skillEntity, battleController)
    local eliminateEffects = skillEntity:getEliminateEffects(battleController)
    if not eliminateEffects then
        return
    end
    local effectList
    for _, buffEntity in ipairs(eliminateEffects) do
        if not effectList then
            effectList = {}
        end
        table.insert(effectList, buffEntity)
    end
    if effectList then
        local unit = {
            name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
            effectList = effectList
        }
        table.insert(instructions, unit)
    end
end

local generateLinkEffects = function(instructions, skillEntity, elementType)
    if not skillEntity:getLinkEffects() or not elementType then
        return
    end

    local effectList
    for type, buffEntities in pairs(skillEntity:getLinkEffects()) do
        local buffEntity = buffEntities[elementType]
        if buffEntity then
            if not effectList then
                effectList = {}
            end
            table.insert(effectList, buffEntity)
        end
    end
    if effectList then
        local unit = {
            name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
            effectList = effectList
        }
        table.insert(instructions, unit)
    end
end

local generateInfluenceEffects = function(instructions, skillEntity, influenceElementTypeMap)
    if not skillEntity:getInInfluenceEffects() or not influenceElementTypeMap then
        return
    end
    for influenceElementType , _ in pairs(influenceElementTypeMap) do
        local effectList
        for type, buffEntities in pairs(skillEntity:getInInfluenceEffects()) do
            local buffEntity = buffEntities[influenceElementType]
            if buffEntity then
                if not effectList then
                    effectList = {}
                end
                table.insert(effectList, buffEntity)
            end
        end
        if effectList then
            table.insert(instructions, {
                name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
                effectList = effectList
            })
        end
    end
end

local generateElementCountEffect = function(instructions, skillEntity, elementType, lineCount)
    if not skillEntity:getElementCountEffect() or not elementType then
        return
    end

    local effectList
    for rogueSkill, list in pairs(skillEntity:getElementCountEffect()) do
        for index, buffEntities in pairs(list) do
            local originBuffEntity = buffEntities.origin
            local useBuffEntity = buffEntities.use
            if not effectList then
                effectList = {}
            end
            local newNum = originBuffEntity:getEffectNum() * lineCount
            useBuffEntity:setEffectNum(newNum)
            table.insert(effectList, useBuffEntity)
        end
    end
    if effectList then
        table.insert(instructions, {
            name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
            effectList = effectList
        })
    end
end

local generateSkillAttackBeforeEffects = function(instructions, skillEntity)
    if not skillEntity:getSkillAttackBeforeEffects() then
        return
    end

    local effectList
    for rogueSkill, list in pairs(skillEntity:getSkillAttackBeforeEffects()) do
        for index, buffEntity in pairs(list) do
            if not effectList then
                effectList = {}
            end
            table.insert(effectList, buffEntity)
        end
    end
    if effectList then
        table.insert(instructions, {
            name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
            effectList = effectList
        })
    end
end

local generateLinkCountMoreEffects = function(instructions, skillEntity, lineCount)
    if not skillEntity:getLinkCountMoreEffects() then
        return
    end

    local effectList
    for rogueSkill, list in pairs(skillEntity:getLinkCountMoreEffects()) do
        for index, info in pairs(list) do
            if info.paramsCount and info.paramsCount <= lineCount then
                if not effectList then
                    effectList = {}
                end
                table.insert(effectList, info.buffEntity)
            end
        end
    end
    if effectList then
        table.insert(instructions, {
            name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
            effectList = effectList
        })
    end
end

local generateLinkCountPowerEffects = function(instructions, skillEntity, lineCount)
    if not skillEntity:getLinkCountPowerEffects() then
        return
    end

    local effectList
    for rogueSkill, list in pairs(skillEntity:getLinkCountPowerEffects()) do
        for index, info in pairs(list) do
            if info.paramsCount and info.paramsCount <= lineCount then
                local power = lineCount // info.paramsCount
                if not effectList then
                    effectList = {}
                end
                local newNum = info.originBuffEntity:getEffectNum() * power
                info.useBuffEntity:setEffectNum(newNum)
                table.insert(effectList, info.useBuffEntity)
            end
        end
    end
    if effectList then
        table.insert(instructions, {
            name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
            effectList = effectList
        })
    end
end

BattleInstructionsHelper._generateBuffInstructions = function(instructions, skillEntity, elementType, lineCount, influenceElementTypeMap, battleController)
    if skillEntity then
        generateEliminateEffects(instructions, skillEntity, battleController)
        generateLinkEffects(instructions, skillEntity, elementType)
        generateInfluenceEffects(instructions, skillEntity, influenceElementTypeMap)
        generateElementCountEffect(instructions, skillEntity, elementType, lineCount)
        generateSkillAttackBeforeEffects(instructions, skillEntity)
        generateLinkCountMoreEffects(instructions, skillEntity, lineCount)
        generateLinkCountPowerEffects(instructions, skillEntity, lineCount)
    end
end

BattleInstructionsHelper.generateInstructions = function(skillEntity, elementType, lineCount, influenceElementTypeMap, elementTypeMap, battleController)
    local elementTypeCount = 0
    local instructions = {}
    -- local assistingList = nil
    ---- 援助
    for element, count in pairs(elementTypeMap) do
        -- if element == elementType then
            elementTypeCount = elementTypeCount + count
        -- else
        --     if assistingList == nil then
        --         assistingList = {}
        --     end
        --     local obj = {
        --         count = count,
        --         skillMatch = element,
        --     }
        --     table.insert(assistingList, obj)
        -- end
    end
    battleController:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.ELIMINATION_COUNT, elementTypeCount)
    if lineCount >= 6 then
        battleController:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.LINK_COUNT_OVER_6, 1)
    end
    if lineCount >= 8 then
        battleController:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.LINK_COUNT_OVER_8, 1)
    end

    -- 攻击
    BattleInstructionsHelper._generateAttackInstructions(instructions, skillEntity, elementType, elementTypeCount)
    ---- 加buff
    BattleInstructionsHelper._generateBuffInstructions(instructions, skillEntity, elementType, lineCount, influenceElementTypeMap, battleController)

    return instructions
end

return BattleInstructionsHelper
