/*
 * Copyright 2020 The casbin Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "casbin/pch.h"

#ifndef DEFAULT_EFFECTOR_CPP
#define DEFAULT_EFFECTOR_CPP

#include "casbin/effect/default_effector.h"
#include "casbin/exception/unsupported_operation_exception.h"

namespace casbin {

/**
 * MergeEffects merges all matching results collected by the enforcer into a single decision.
 */
Effect DefaultEffector::MergeEffects(const std::string& expr, const std::vector<Effect>& effects, const std::vector<float>& matches, int policyIndex, int policyLength, int& explainIndex) {
    Effect result = Effect::Indeterminate;
    explainIndex = -1;

    if (expr == "some(where (p.eft == allow))") { // AllowOverrideEffect
        if (matches[policyIndex] == 0) {
            return result;
        }

        // only check the current policyIndex
        if (effects[policyIndex] == Effect::Allow) {
            result = Effect::Allow;
            explainIndex = policyIndex;
            return result;
        }
    } else if (expr == "!some(where (p.eft == deny))") { // DenyOverrideEffect
        // only check the current policyIndex
        if (matches[policyIndex] != 0 && effects[policyIndex] == Effect::Deny) {
            result = Effect::Deny;
            explainIndex = policyIndex;
            return result;
        }

        // if no deny rules are matched  at last, then allow
        if (policyIndex == policyLength - 1) {
            result = Effect::Allow;
            return result;
        }
    } else if (expr == "some(where (p.eft == allow)) && !some(where (p.eft == deny))") { // AllowAndDenyEffect
        // short-circuit if matched deny rule
        if (matches[policyIndex] != 0 && effects[policyIndex] == Effect::Deny) {
            result = Effect::Deny;
            // set hit rule to the (first) matched deny rule
            explainIndex = policyIndex;
            return result;
        }

        // short-circuit some effects in the middle
        if (policyIndex < policyLength - 1) {
            // choose not to short-circuit
            return result;
        }

        // merge all effects at last
        for (int i = 0; i < effects.size(); ++i) {
            if (matches[i] == 0) {
                continue;
            }

            if (effects[i] == Effect::Allow) {
                result = Effect::Allow;
                // set hit rule to first matched allow rule
                explainIndex = i;
                return result;
            }
        }

    } else if (expr == "priority(p.eft) || deny") { // PriorityEffect
        // reverse merge, short-circuit may be earlier
        for (int i = effects.size() - 1; i >= 0; --i) {
            if (matches[i] == 0) {
                continue;
            }

            if (effects[i] != Effect::Indeterminate) {
                if (effects[i] == Effect::Allow) {
                    result = Effect::Allow;
                } else {
                    result = Effect::Deny;
                }
                explainIndex = i;
                return result;
            }
        }

    } else {
        throw UnsupportedOperationException("unsupported effect");
    }

    return result;
}

} // namespace casbin

#endif // DEFAULT_EFFECTOR_CPP
