-- Rush Duel 融合术/结合
RushDuel = RushDuel or {}

-- 添加 融合术/结合 素材
function RushDuel.AddFusionProcedure(card, ...)
    Auxiliary.AddFusionProcMix(card, true, true, table.unpack({...}))
end

-- 创建效果: 融合术/结合 召唤
function RushDuel.CreateFusionEffect(card, matfilter, spfilter, exfilter, s_range, o_range, mat_check, mat_move, target_action, operation_action)
    local self_range = s_range or 0
    local opponent_range = o_range or 0
    local move = mat_move or RushDuel.FusionToGrave
    local e = Effect.CreateEffect(card)
    e:SetTarget(RushDuel.FusionTarget(matfilter, spfilter, exfilter, self_range, opponent_range, mat_check, target_action))
    e:SetOperation(RushDuel.FusionOperation(matfilter, spfilter, exfilter, self_range, opponent_range, mat_check, move, operation_action))
    return e
end
function RushDuel.FusionMaterialFilter(c, filter, e)
    return (not filter or filter(c)) and (not e or not c:IsImmuneToEffect(e))
end
function RushDuel.FusionSpecialSummonFilter(c, e, tp, m, f, chkf, filter)
    return c:IsType(TYPE_FUSION) and (not filter or filter(c)) and (not f or f(c)) and c:IsCanBeSpecialSummoned(e, SUMMON_TYPE_FUSION, tp, false, false) and c:CheckFusionMaterial(m, nil, chkf)
end
function RushDuel.FusionTarget(matfilter, spfilter, exfilter, s_range, o_range, mat_check, action)
    return function(e, tp, eg, ep, ev, re, r, rp, chk)
        if chk == 0 then
            local chkf = tp
            local mg1 = Duel.GetFusionMaterial(tp):Filter(RushDuel.FusionMaterialFilter, nil, matfilter)
            if s_range ~= 0 or o_range ~= 0 then
                local mg2 = Duel.GetMatchingGroup(exfilter, tp, s_range, o_range, nil)
                mg1:Merge(mg2)
            end
            aux.FGoalCheckAdditional = mat_check
            local res = Duel.IsExistingMatchingCard(RushDuel.FusionSpecialSummonFilter, tp, LOCATION_EXTRA, 0, 1, nil, e, tp, mg1, nil, chkf, spfilter)
            if not res then
                local ce = Duel.GetChainMaterial(tp)
                if ce ~= nil then
                    local fgroup = ce:GetTarget()
                    local mg3 = fgroup(ce, e, tp)
                    local mf = ce:GetValue()
                    res = Duel.IsExistingMatchingCard(RushDuel.FusionSpecialSummonFilter, tp, LOCATION_EXTRA, 0, 1, nil, e, tp, mg3, mf, chkf, spfilter)
                end
            end
            aux.FGoalCheckAdditional = nil
            return res
        end
        if action ~= nil then
            action(e, tp, eg, ep, ev, re, r, rp)
        end
        Duel.SetOperationInfo(0, CATEGORY_SPECIAL_SUMMON, nil, 1, tp, LOCATION_EXTRA)
    end
end
function RushDuel.FusionOperation(matfilter, spfilter, exfilter, s_range, o_range, mat_check, mat_move, action)
    return function(e, tp, eg, ep, ev, re, r, rp)
        local chkf = tp
        local mg1 = Duel.GetFusionMaterial(tp):Filter(RushDuel.FusionMaterialFilter, nil, matfilter, e)
        if s_range ~= 0 or o_range ~= 0 then
            local mg2 = Duel.GetMatchingGroup(exfilter, tp, s_range, o_range, nil, e)
            mg1:Merge(mg2)
        end
        aux.FGoalCheckAdditional = mat_check
        local sg1 = Duel.GetMatchingGroup(RushDuel.FusionSpecialSummonFilter, tp, LOCATION_EXTRA, 0, nil, e, tp, mg1, nil, chkf, spfilter)
        local mg3 = nil
        local sg2 = nil
        local ce = Duel.GetChainMaterial(tp)
        if ce ~= nil then
            local fgroup = ce:GetTarget()
            mg3 = fgroup(ce, e, tp)
            local mf = ce:GetValue()
            sg2 = Duel.GetMatchingGroup(RushDuel.FusionSpecialSummonFilter, tp, LOCATION_EXTRA, 0, nil, e, tp, mg3, mf, chkf, spfilter)
        end
        local mat = nil
        local fc = nil
        if sg1:GetCount() > 0 or (sg2 ~= nil and sg2:GetCount() > 0) then
            local sg = sg1:Clone()
            if sg2 then
                sg:Merge(sg2)
            end
            Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_SPSUMMON)
            local tg = sg:Select(tp, 1, 1, nil)
            fc = tg:GetFirst()
            if sg1:IsContains(fc) and (sg2 == nil or not sg2:IsContains(fc) or not Duel.SelectYesNo(tp, ce:GetDescription())) then
                mat = Duel.SelectFusionMaterial(tp, fc, mg1, nil, chkf)
                fc:SetMaterial(mat)
                mat_move(mat)
                Duel.BreakEffect()
                Duel.SpecialSummon(fc, SUMMON_TYPE_FUSION, tp, tp, false, false, POS_FACEUP)
            else
                mat = Duel.SelectFusionMaterial(tp, fc, mg3, nil, chkf)
                local fop = ce:GetOperation()
                fop(ce, e, tp, fc, mat)
            end
            fc:CompleteProcedure()
        end
        if action ~= nil then
            action(e, tp, eg, ep, ev, re, r, rp, mat, fc)
        end
        aux.FGoalCheckAdditional = nil
    end
end

-- 素材去向: 墓地
function RushDuel.FusionToGrave(mat)
    Duel.SendtoGrave(mat, REASON_EFFECT + REASON_MATERIAL + REASON_FUSION)
end
-- 素材去向: 卡组
function RushDuel.FusionToDeck(mat)
    Duel.SendtoDeck(mat, nil, SEQ_DECKSHUFFLE, REASON_EFFECT + REASON_MATERIAL + REASON_FUSION)
end
