-- 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 -- 幻刃封锁 (不能选择不能攻击的种族)

-- 创建效果: 玩家对象的全局效果
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
-- 创建效果: 只能用特定类型的怪兽攻击 (对玩家效果)
function RushDuel.CreateAttackLimitEffect(e, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能攻击 (对玩家效果)
function RushDuel.CreateCannotAttackEffect(e, hint, player, s_range, o_range, reset)
    local s_target, o_traget = 0, 0
    if s_range == 1 then
        s_target = LOCATION_MZONE
    end
    if o_range == 1 then
        o_traget = LOCATION_MZONE
    end
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_target, o_traget)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetDescription(hint)
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_PLAYER_CANNOT_ATTACK)
    e2:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e2:SetTargetRange(s_range, o_range)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
    return e1, e2
end
-- 创建效果: 不能用某些种族攻击 (对玩家效果)
function RushDuel.CreateRaceCannotAttackEffect(e, hint, race, player, s_range, o_range, reset)
    local s_target, o_traget = 0, 0
    if s_range == 1 then
        s_target = LOCATION_MZONE
    end
    if o_range == 1 then
        o_traget = LOCATION_MZONE
    end
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_target, o_traget)
    e1:SetTarget(function(e, c)
        return c:IsRace(race)
    end)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetDescription(hint)
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_PLAYER_RACE_CANNOT_ATTACK)
    e2:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e2:SetTargetRange(s_range, o_range)
    e2:SetValue(race)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
    return e1, e2
end
-- 创建效果: 不能直接攻击 (对玩家效果)
function RushDuel.CreateCannotDirectAttackEffect(e, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_DIRECT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能选择攻击目标 (对玩家效果)
function RushDuel.CreateCannotSelectBattleTargetEffect(e, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_SELECT_BATTLE_TARGET)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能召唤怪兽 (对玩家效果)
function RushDuel.CreateCannotSummonEffect(e, desc, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_SUMMON)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能盖放怪兽 (对玩家效果)
function RushDuel.CreateCannotSetMonsterEffect(e, desc, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_MSET)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能特殊召唤怪兽 (对玩家效果)
function RushDuel.CreateCannotSpecialSummonEffect(e, desc, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_SPECIAL_SUMMON)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 只能用1只怪兽进行攻击 (对玩家效果)
function RushDuel.CreateOnlySoleAttackEffect(e, code, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD + EFFECT_TYPE_CONTINUOUS)
    e1:SetCode(EVENT_ATTACK_ANNOUNCE)
    e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
    e1:SetOperation(function(e, tp, eg, ep, ev, re, r, rp)
        if Duel.GetFlagEffect(tp, code) == 0 then
            e:GetLabelObject():SetLabel(eg:GetFirst():GetFieldID())
            Duel.RegisterFlagEffect(tp, code, reset, 0, 1)
        end
    end)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_CANNOT_ATTACK_ANNOUNCE)
    e2:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e2:SetTargetRange(s_range, o_range)
    e2:SetCondition(function(e)
        return Duel.GetFlagEffect(e:GetHandlerPlayer(), code) ~= 0
    end)
    e2:SetTarget(function(e, c)
        return c:GetFieldID() ~= e:GetLabel()
    end)
    e1:SetLabelObject(e2)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
end
-- 创建效果: 只能用这张卡进行攻击 (对玩家效果)
function RushDuel.CreateOnlyThisAttackEffect(e, code, player, s_range, o_range, reset)
    local c = e:GetHandler()
    local e1 = Effect.CreateEffect(c)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK_ANNOUNCE)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetLabelObject(c)
    e1:SetTargetRange(s_range, o_range)
    e1:SetTarget(function(e, c)
        return not (c == e:GetLabelObject() and c:GetFlagEffect(code) ~= 0)
    end)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    c:RegisterFlagEffect(code, RESET_EVENT + RESETS_STANDARD - RESET_TURN_SET + reset, 0, 1)
end
-- 创建效果: 不能把效果发动 (对玩家效果)
function RushDuel.CreateCannotActivateEffect(e, desc, value, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ACTIVATE)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if value ~= nil then
        e1:SetValue(value)
    end
    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 value ~= nil then
        e1:SetValue(value)
    end
    if desc ~= nil then
        e1:SetDescription(desc)
        e1:SetProperty(EFFECT_FLAG_CLIENT_HINT)
    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, category1, category2)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_IGNITION)
    e1:SetRange(LOCATION_MZONE)
    local e2 = e1:Clone()
    e1:SetDescription(hint1)
    e2:SetDescription(hint2)
    e1:SetCategory(category1 or 0)
    e2:SetCategory(category2 or 0)
    if condition ~= nil then
        e1:SetCondition(condition)
        e2:SetCondition(condition)
    end
    if cost ~= nil then
        e1:SetCost(cost)
        e2:SetCost(cost)
    end
    if target1 ~= nil then
        e1:SetTarget(target1)
    end
    if target2 ~= nil then
        e2:SetTarget(target2)
    end
    e1:SetOperation(operation1)
    e2:SetOperation(operation2)
    card:RegisterEffect(e1)
    card:RegisterEffect(e2)
    return e1, e2
end

-- 添加通常召唤手续
function RushDuel.AddSummonProcedure(card, desc, condition, operation, value)
    local e1 = Effect.CreateEffect(card)
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(EFFECT_SUMMON_PROC)
    e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE)
    e1:SetCondition(condition)
    if operation ~= nil then
        e1:SetOperation(operation)
    end
    if value ~= nil then
        e1:SetValue(value)
    end
    card:RegisterEffect(e1)
    return e1
end
-- 添加手卡特殊召唤手续
function RushDuel.AddHandSpecialSummonProcedure(card, desc, condition, target, operation, value, position)
    local e1 = Effect.CreateEffect(card)
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_SPSUMMON_PROC)
    if position == nil then
        e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE)
    else
        e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE + EFFECT_FLAG_UNCOPYABLE + EFFECT_FLAG_SPSUM_PARAM)
        e1:SetTargetRange(position, 0)
    end
    e1:SetRange(LOCATION_HAND)
    if condition ~= nil then
        e1:SetCondition(condition)
    end
    if target ~= nil then
        e1:SetTarget(target)
    end
    if operation ~= nil then
        e1:SetOperation(operation)
    end
    if value ~= nil then
        e1:SetValue(value)
    end
    card:RegisterEffect(e1)
    return e1
end

-- 上级召唤时的解放怪兽检测
function RushDuel.CreateAdvanceCheck(card, filter, count, flag)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(EFFECT_MATERIAL_CHECK)
    e1:SetValue(function(e, c)
        local mg = c:GetMaterial()
        local ct = math.min(count, mg:GetCount())
        local label = 0
        if c:IsLevelBelow(6) and count == 2 then
            -- 当前等级小于解放要求
        elseif ct > 0 and mg:IsExists(filter, ct, nil, e) then
            label = flag
        end
        e:SetLabel(label)
    end)
    card:RegisterEffect(e1)
    local e2 = Effect.CreateEffect(card)
    e2:SetType(EFFECT_TYPE_SINGLE + EFFECT_TYPE_CONTINUOUS)
    e2:SetCode(EVENT_SUMMON_SUCCESS)
    e2:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
    e2:SetLabelObject(e1)
    e2:SetCondition(RushDuel.AdvanceCheckCondition)
    e2:SetOperation(RushDuel.AdvanceCheckOperation)
    card:RegisterEffect(e2)
    return e1, e2
end
function RushDuel.AdvanceCheckCondition(e, tp, eg, ep, ev, re, r, rp)
    return e:GetLabelObject():GetLabel() ~= 0 and e:GetHandler():IsSummonType(SUMMON_TYPE_ADVANCE)
end
function RushDuel.AdvanceCheckOperation(e, tp, eg, ep, ev, re, r, rp)
    e:GetHandler():RegisterFlagEffect(e:GetLabelObject():GetLabel(), RESET_EVENT + RESETS_STANDARD, 0, 1)
end

-- 记录召唤的解放数量
function RushDuel.CreateAdvanceCount(card, self_value)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(EFFECT_MATERIAL_CHECK)
    e1:SetValue(function(e, c)
        if c:IsSummonType(SUMMON_VALUE_SELF) then
            e:SetLabel(self_value)
        elseif c:IsLevelBelow(4) then
            e:SetLabel(0)
        elseif c:IsLevelBelow(6) then
            e:SetLabel(1)
        else
            e:SetLabel(2)
        end
    end)
    card:RegisterEffect(e1)
    return e1
end

-- 记录攻击表示上级召唤的状态
function RushDuel.CreateAdvanceSummonFlag(card, flag)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_SINGLE + EFFECT_TYPE_CONTINUOUS)
    e1:SetCode(EVENT_SUMMON_SUCCESS)
    e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
    e1:SetLabel(flag)
    e1:SetCondition(RushDuel.AdvanceSummonFlagCondition)
    e1:SetOperation(RushDuel.AdvanceSummonFlagOperation)
    card:RegisterEffect(e1)
    return e1
end
function RushDuel.AdvanceSummonFlagCondition(e, tp, eg, ep, ev, re, r, rp)
    return e:GetHandler():IsSummonType(SUMMON_TYPE_ADVANCE)
end
function RushDuel.AdvanceSummonFlagOperation(e, tp, eg, ep, ev, re, r, rp)
    e:GetHandler():RegisterFlagEffect(e:GetLabel(), RESET_EVENT + RESETS_STANDARD, 0, 1)
end

-- 三重解放 (临时处理方法)
function RushDuel.CreateTripleTribute(source, card, desc, value, forced)
    local e1 = Effect.CreateEffect(source)
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_SUMMON_PROC)
    e1:SetRange(LOCATION_MZONE)
    e1:SetTargetRange(LOCATION_HAND, 0)
    e1:SetCondition(RushDuel.TripleTributeCondition)
    e1:SetTarget(RushDuel.TripleTributeTarget(value))
    e1:SetOperation(RushDuel.TripleTributeOperation)
    e1:SetValue(SUMMON_TYPE_ADVANCE + SUMMON_VALUE_SELF)
    card:RegisterEffect(e1, forced)
    return e1
end
function RushDuel.TripleTributeCondition(e, c, minc)
    if c == nil then
        return true
    end
    local tc = e:GetHandler()
    local tp = c:GetControler()
    local mg = Duel.GetTributeGroup(c)
    return minc <= 3 and mg:IsContains(tc) and Duel.GetMZoneCount(tp, tc) > 0
end
function RushDuel.TripleTributeTarget(value)
    return function(e, c)
        return value(e, c) and c:IsCode(120235000, 120253004)
    end
end
function RushDuel.TripleTributeOperation(e, tp, eg, ep, ev, re, r, rp, c)
    local mg = Group.FromCards(e:GetHandler())
    c:SetMaterial(mg)
    Duel.Release(mg, REASON_SUMMON + REASON_MATERIAL)
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.AddContinuousEffect(c, ...)
    if c:IsStatus(STATUS_COPYING_EFFECT) then
        return
    end
    if c.continuous_effect == nil then
        local mt = getmetatable(c)
        mt.continuous_effect = {...}
    else
        for _, e in ipairs {...} do
            table.insert(c.continuous_effect, e)
        end
    end
end

-- 获取效果值列表
function RushDuel.GetEffectValues(card, code)
    local effects = {card:IsHasEffect(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
