-- Rush Duel 基础
RushDuel = RushDuel or {}

-- 新种族
RACE_MAGICALKNIGHT = 0x4000000 -- 魔导骑士
RACE_HYDRAGON = 0x8000000 -- 多头龙
RACE_OMEGAPSYCHO = 0x10000000 -- 欧米茄念动力
RACE_CELESTIALWARRIOR = 0x20000000 -- 天界战士
RACE_GALAXY = 0x40000000 -- 银河
RACE_CYBORG = 0x80000000 -- 电子人

RACE_ALL = 0xffffffff

-- 特殊调整
EFFECT_LEGEND_CARD = 120000000 -- 传说卡标识 (改变卡名不影响)
EFFECT_CANNOT_SINGLE_TRIBUTE = 120170045 -- 监狱岛 大姐头巨岩 (与下面的效果结合变成不能上级召唤)
EFFECT_CANNOT_DOUBLE_TRIBUTE = 120120029 -- 魔将 雅灭鲁拉 (不能使用：双重解放)
EFFECT_PLAYER_CANNOT_ATTACK = 120155054 -- 幻刃封锁 (对方不能攻击时不能发动)
EFFECT_PLAYER_RACE_CANNOT_ATTACK = 120155055 -- 幻刃封锁 (不能选择不能攻击的种族)
EFFECT_PLAYER_CANNOT_ACTIVATE_TRAP = 120247013 -- 三角神迷火花 (整个回合不能发动陷阱)
EFFECT_PLAYER_CANNOT_ACTIVATE_TRAP_BATTLE = 120261022 -- 暗物质人偶·水母 (战斗阶段不能发动陷阱)
EFFECT_ATTACK_NOT_CHAIN_TRAP = 120140004 -- 不许始末战士 (攻击宣言时, 对方不能把陷阱卡发动)
EFFECT_ONLY_FUSION_SUMMON = 120263031 -- 只能融合召唤 (奇迹融合)
EFFECT_MAXIMUM_MODE = 120272058 -- 通过效果变成极大模式 (时间机器)
EFFECT_CANNOT_TO_HAND_EFFECT = EFFECT_CANNOT_TO_HAND -- 不会被效果回到手卡
EFFECT_CANNOT_TO_DECK_EFFECT = EFFECT_CANNOT_TO_DECK -- 不会被效果回到卡组·额外卡组

FLAG_SUMMON_TURN = 120000011 -- 召唤·特殊召唤的回合被盖放, 不再符合召唤·特殊召唤的回合的条件
FLAG_ATTACK_ANNOUNCED = 120000012 -- 已经进行了攻击宣言, 不能向怪兽攻击的效果失效
FLAG_ATTACH_EFFECT = 120000013 -- 通过效果赋予的效果, 不能重复叠加

-- 创建效果: 这张卡不能特殊召唤
function RushDuel.CannotSpecialSummon(card, range)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(EFFECT_SPSUMMON_CONDITION)
    if range then
        e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE + EFFECT_FLAG_SINGLE_RANGE)
        e1:SetRange(range)
    else
        e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE)
    end
    card:RegisterEffect(e1)
    return e1
end
-- 创建效果: 这张卡不用融合术召唤不能特殊召唤
function RushDuel.OnlyFusionSummon(card)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(EFFECT_SPSUMMON_CONDITION)
    e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE)
    e1:SetValue(aux.fuslimit)
    card:RegisterEffect(e1)
    local e2 = Effect.CreateEffect(card)
    e2:SetType(EFFECT_TYPE_SINGLE)
    e2:SetCode(EFFECT_ONLY_FUSION_SUMMON)
    e2:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE)
    card:RegisterEffect(e2)
    return e1, e2
end
-- 创建效果: 玩家对象的全局效果
function RushDuel.CreatePlayerTargetGlobalEffect(code, value)
    local e1 = Effect.GlobalEffect()
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(code)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
    e1:SetTargetRange(1, 1)
    if value ~= nil then
        e1:SetValue(value)
    end
    Duel.RegisterEffect(e1, 0)
    return e1
end
-- 创建效果: 影响全场的全局效果
function RushDuel.CreateFieldGlobalEffect(is_continuous, code, operation)
    local e1 = Effect.GlobalEffect()
    if is_continuous then
        e1:SetType(EFFECT_TYPE_FIELD + EFFECT_TYPE_CONTINUOUS)
    else
        e1:SetType(EFFECT_TYPE_FIELD)
    end
    e1:SetCode(code)
    e1:SetOperation(operation)
    Duel.RegisterEffect(e1, 0)
    return e1
end
-- 创建效果: 在LP槽显示提示信息
function RushDuel.CreateHintEffect(e, desc, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: Buff类效果
function RushDuel.CreateSingleEffect(e, desc, card, code, value, reset, forced)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(code)
    if desc ~= nil then
        e1:SetDescription(desc)
        e1:SetProperty(EFFECT_FLAG_CLIENT_HINT)
    end
    e1:SetLabel(FLAG_ATTACH_EFFECT)
    if value ~= nil then
        e1:SetValue(value)
    end
    if reset ~= nil then
        e1:SetReset(reset)
    end
    card:RegisterEffect(e1, forced)
    return e1
end
-- 创建效果: 选择效果
function RushDuel.CreateMultiChooseEffect(card, condition, cost, hint1, target1, operation1, hint2, target2, operation2)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_IGNITION)
    e1:SetRange(LOCATION_MZONE)
    if condition ~= nil then
        e1:SetCondition(condition)
    end
    if cost ~= nil then
        e1:SetCost(cost)
    end
    local e2 = e1:Clone()
    e1:SetDescription(hint1)
    e2:SetDescription(hint2)
    e1:SetTarget(RushDuel.MultiChooseEffectTarget(target1))
    e2:SetTarget(RushDuel.MultiChooseEffectTarget(target2))
    e1:SetOperation(operation1)
    e2:SetOperation(operation2)
    card:RegisterEffect(e1)
    card:RegisterEffect(e2)
    return e1, e2
end
function RushDuel.MultiChooseEffectTarget(target)
    if target ~= nil then
        return target
    else
        return function(e, tp, eg, ep, ev, re, r, rp, chk)
            if chk == 0 then
                return true
            end
            Duel.Hint(HINT_OPSELECTED, 1 - tp, e:GetDescription())
        end
    end
end

-- 添加记述卡牌列表
function RushDuel.AddCodeList(card, ...)
    for _, list in ipairs {...} do
        local type = aux.GetValueType(list)
        if type == "number" then
            aux.AddCodeList(card, list)
        elseif type == "table" then
            aux.AddCodeList(card, table.unpack(list))
        end
    end
end

-- 获取附加的效果
function RushDuel.GetAttachEffects(card, code)
    local effects = {card:IsHasEffect(code)}
    local attachs = {}
    for i, effect in ipairs(effects) do
        if effect:GetLabel() == FLAG_ATTACH_EFFECT then
            table.insert(attachs, effect)
        end
    end
    return attachs
end

-- 获取效果值列表
function RushDuel.GetEffectValues(card, code)
    local effects = RushDuel.GetAttachEffects(card, code)
    local values = {}
    for i, effect in ipairs(effects) do
        values[i] = effect:GetValue()
    end
    return values
end

-- 抹平表
function RushDuel.FlatTable(...)
    local result = {}
    for _, item in ipairs({...}) do
        if type(item) == "table" then
            local datas = RushDuel.FlatTable(table.unpack(item))
            for _, data in ipairs(datas) do
                table.insert(result, data)
            end
        else
            table.insert(result, item)
        end
    end
    return result
end
-- 递归检查表
function RushDuel.FlatCheck(check, ...)
    for _, item in ipairs({...}) do
        if type(item) == "table" then
            if RushDuel.FlatCheck(check, table.unpack(item)) then
                return true
            end
        elseif check(item) then
            return true
        end
    end
    return false
end

-- 重载 ForEach
if not Group.ForEach then
    Group.ForEach = function(g, func, ...)
        local tc = g:GetFirst()
        while tc do
            func(tc, ...)
            tc = g:GetNext()
        end
    end
end
