/*
 * 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 ENFORCER_CACHED_CPP
#define ENFORCER_CACHED_CPP

#include "casbin/effect/default_effector.h"
#include "casbin/enforcer_cached.h"
#include "casbin/exception/casbin_adapter_exception.h"
#include "casbin/exception/casbin_enforcer_exception.h"
#include "casbin/persist/file_adapter/file_adapter.h"
#include "casbin/persist/watcher_ex.h"
#include "casbin/rbac/default_role_manager.h"
#include "casbin/util/util.h"

namespace casbin {

/**
 * Enforcer is the default constructor.
 */
CachedEnforcer ::CachedEnforcer() {
    this->enableCache = true;
}

/**
 * Enforcer initializes an enforcer with a model file and a policy file.
 *
 * @param model_path the path of the model file.
 * @param policyFile the path of the policy file.
 */
CachedEnforcer ::CachedEnforcer(const std::string& model_path, const std::string& policy_file)
    : Enforcer(model_path, policy_file) {
    this->enableCache = true;
}

/**
 * Enforcer initializes an enforcer with a database adapter.
 *
 * @param model_path the path of the model file.
 * @param adapter the adapter.
 */
CachedEnforcer ::CachedEnforcer(const std::string& model_path, std::shared_ptr<Adapter> adapter)
    : Enforcer(model_path, adapter) {
    this->enableCache = true;
}

/**
 * Enforcer initializes an enforcer with a model and a database adapter.
 *
 * @param m the model.
 * @param adapter the adapter.
 */
CachedEnforcer ::CachedEnforcer(const std::shared_ptr<Model>& m, std::shared_ptr<Adapter> adapter)
    : Enforcer(m, adapter) {
    this->enableCache = true;
}

/**
 * Enforcer initializes an enforcer with a model.
 *
 * @param m the model.
 */
CachedEnforcer ::CachedEnforcer(const std::shared_ptr<Model>& m)
    : Enforcer(m) {
    this->enableCache = true;
}

/**
 * Enforcer initializes an enforcer with a model file.
 *
 * @param model_path the path of the model file.
 */
CachedEnforcer ::CachedEnforcer(const std::string& model_path)
    : Enforcer(model_path) {
    this->enableCache = true;
}

/**
 * Enforcer initializes an enforcer with a model file, a policy file and an enable log flag.
 *
 * @param model_path the path of the model file.
 * @param policyFile the path of the policy file.
 * @param enableLog whether to enable Casbin's log.
 */
CachedEnforcer ::CachedEnforcer(const std::string& model_path, const std::string& policy_file, bool enable_log)
    : Enforcer(model_path, policy_file, enable_log) {
    this->enableCache = true;
}

CachedEnforcer::CachedEnforcer(const CachedEnforcer& ce)
    : Enforcer(ce) {
    this->m = ce.m;
    this->enableCache = ce.enableCache;
}

CachedEnforcer::CachedEnforcer(CachedEnforcer&& ce) noexcept
    : Enforcer(ce) {
    this->m = std::move(ce.m);
    this->enableCache = ce.enableCache;
}

void CachedEnforcer::EnableCache(const bool& shouldEnableCache) {
    this->enableCache = shouldEnableCache;
}

std::pair<bool, bool> CachedEnforcer::getCachedResult(const std::string& key) {
    locker.lock();
    bool ok = m.count(key);
    if (!ok) {
        locker.unlock();
        return std::pair<bool, bool>(false, false);
    }

    std::pair<bool, bool> res_ok(m[key], ok);
    locker.unlock();
    return res_ok;
}

void CachedEnforcer::setCachedResult(const std::string& key, const bool& res) {
    locker.lock();
    m[key] = res;
    locker.unlock();
}

void CachedEnforcer::InvalidateCache() {
    m.clear();
}

// Enforce decides whether a "subject" can access a "object" with the operation
// "action", input parameters are usually: (sub, obj, act).
bool CachedEnforcer ::Enforce(std::shared_ptr<IEvaluator> evalator) {
    return EnforceWithMatcher("", evalator);
}

bool CachedEnforcer::Enforce(const DataVector& params) {
    return EnforceWithMatcher("", params);
}

// Enforce with a vector param,decides whether a "subject" can access a "object"
// with the operation "action", input parameters are usually: (sub, obj, act).
bool CachedEnforcer::Enforce(const DataList& params) {
    return EnforceWithMatcher("", params);
}

// Enforce with a map param,decides whether a "subject" can access a "object"
// with the operation "action", input parameters are usually: (sub, obj, act).
bool CachedEnforcer::Enforce(const DataMap& params) {
    return EnforceWithMatcher("", params);
}

// EnforceWithMatcher use a custom matcher to decides whether a "subject" can
// access a "object" with the operation "action", input parameters are usually:
// (matcher, sub, obj, act), use model matcher by default when matcher is "".
bool CachedEnforcer ::EnforceWithMatcher(const std::string& matcher, std::shared_ptr<IEvaluator> evalator) {
    return Enforcer::EnforceWithMatcher(matcher, evalator);
}

// EnforceWithMatcher use a custom matcher to decides whether a "subject" can
// access a "object" with the operation "action", input parameters are usually:
// (matcher, sub, obj, act), use model matcher by default when matcher is "".
bool CachedEnforcer::EnforceWithMatcher(const std::string& matcher, const DataVector& params) {
    if (!enableCache) {
        return Enforcer::EnforceWithMatcher(matcher, params);
    }

    std::string key;
    for (const auto& r : params) {
        if (const auto string_param = std::get_if<std::string>(&r))
            key += *string_param;
        key += "$$";
    }
    key += matcher;
    key += "$";

    std::pair<bool, bool> res_ok = getCachedResult(key);

    if (res_ok.second) {
        return res_ok.first;
    }

    bool res = Enforcer::EnforceWithMatcher(matcher, params);
    setCachedResult(key, res);
    return res;
}

// EnforceWithMatcher use a custom matcher to decides whether a "subject" can
// access a "object" with the operation "action", input parameters are usually:
// (matcher, sub, obj, act), use model matcher by default when matcher is "".
bool CachedEnforcer::EnforceWithMatcher(const std::string& matcher, const DataList& params) {
    if (!enableCache) {
        return Enforcer::EnforceWithMatcher(matcher, params);
    }

    std::string key;
    for (const auto& r : params) {
        if (const auto string_param = std::get_if<std::string>(&r))
            key += *string_param;
        key += "$$";
    }
    key += matcher;
    key += "$";

    std::pair<bool, bool> res_ok = getCachedResult(key);

    if (res_ok.second) {
        return res_ok.first;
    }

    bool res = Enforcer::EnforceWithMatcher(matcher, params);
    setCachedResult(key, res);
    return res;
}

// EnforceWithMatcher use a custom matcher to decides whether a "subject" can
// access a "object" with the operation "action", input parameters are usually:
// (matcher, sub, obj, act), use model matcher by default when matcher is "".
bool CachedEnforcer::EnforceWithMatcher(const std::string& matcher, const DataMap& params) {
    if (!enableCache) {
        return Enforcer::EnforceWithMatcher(matcher, params);
    }

    std::string key;
    for (auto [param_name, param_value] : params) {
        if (const auto string_value = std::get_if<std::string>(&param_value))
            key += *string_value;
        key += "$$";
    }
    key += matcher;
    key += "$";

    std::pair<bool, bool> res_ok = getCachedResult(key);

    if (res_ok.second) {
        return res_ok.first;
    }

    bool res = Enforcer::EnforceWithMatcher(matcher, params);
    setCachedResult(key, res);
    return res;
}

} // namespace casbin

#endif // ENFORCER_CACHED_CPP
