/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#ifndef COMMON_CACHE_LRU_CACHE_H
#define COMMON_CACHE_LRU_CACHE_H

#include <algorithm>
#include <list>
#include <unordered_map>

#include "utils/errno_define.h"

namespace common {

template <typename K, typename V>
struct KeyValuePair {
   public:
    K key;
    V value;

    KeyValuePair(K k, V v) : key(std::move(k)), value(std::move(v)) {}
};

/**
 *	The LRU Cache class templated by
 *		Key - key type
 *		Value - value type
 *		MapType - an associative container like std::unordered_map
 */
template <class Key, class Value,
          class Map = std::unordered_map<
              Key, typename std::list<KeyValuePair<Key, Value>>::iterator>>
class Cache {
   public:
    typedef KeyValuePair<Key, Value> node_type;
    typedef std::list<KeyValuePair<Key, Value>> list_type;
    typedef Map map_type;
    /**
     * the maxSize is the soft limit of entries and (maxSize + elasticity) is
     * the hard limit the cache is allowed to grow till (maxSize + elasticity)
     * and is pruned back to maxSize entries set maxSize = 0 for an unbounded
     * cache (but in that case, you're better off using a std::unordered_map
     * directly anyway! :)
     */
    explicit Cache(size_t maxSize = 64, size_t elasticity = 10)
        : maxSize_(maxSize), elasticity_(elasticity) {}
    virtual ~Cache() = default;
    size_t size() const { return cache_.size(); }
    bool empty() const { return cache_.empty(); }
    void clear() {
        cache_.clear();
        entries_.clear();
    }
    void insert(const Key& k, Value v) {
        const auto iter = cache_.find(k);
        if (iter != cache_.end()) {
            iter->second->value = v;
            entries_.splice(entries_.begin(), entries_, iter->second);
            return;
        }

        entries_.emplace_front(k, std::move(v));
        cache_[k] = entries_.begin();
        prune();
    }
    /**
      for backward compatibility. redirects to tryGetCopy()
     */
    bool tryGet(const Key& kIn, Value& vOut) { return tryGetCopy(kIn, vOut); }

    bool tryGetCopy(const Key& kIn, Value& vOut) {
        Value tmp;
        if (!tryGetRef_nolock(kIn, tmp)) {
            return false;
        }
        vOut = tmp;
        return true;
    }

    bool tryGetRef(const Key& kIn, Value& vOut) {
        return tryGetRef_nolock(kIn, vOut);
    }
    /**
     *	The const reference returned here is only
     *    guaranteed to be valid till the next insert/delete
     *  in multi-threaded apps use getCopy() to be threadsafe
     */
    const Value& getRef(const Key& k) { return get_nolock(k); }

    /**
        added for backward compatibility
     */
    Value get(const Key& k) { return getCopy(k); }
    /**
     * returns a copy of the stored object (if found)
     * safe to use/recommended in multi-threaded apps
     */
    Value getCopy(const Key& k) { return get_nolock(k); }

    bool remove(const Key& k) {
        auto iter = cache_.find(k);
        if (iter == cache_.end()) {
            return false;
        }
        entries_.erase(iter->second);
        cache_.erase(iter);
        return true;
    }
    bool contains(const Key& k) const { return cache_.find(k) != cache_.end(); }

    size_t getMaxSize() const { return maxSize_; }
    size_t getElasticity() const { return elasticity_; }
    size_t getMaxAllowedSize() const { return maxSize_ + elasticity_; }
    template <typename F>
    void cwalk(F& f) const {
        std::for_each(entries_.begin(), entries_.end(), f);
    }

   protected:
    bool tryGetRef_nolock(const Key& kIn, Value& vOut) {
        const auto iter = cache_.find(kIn);
        if (iter == cache_.end()) {
            return false;
        }
        entries_.splice(entries_.begin(), entries_, iter->second);
        vOut = iter->second->value;
        return true;
    }
    size_t prune() {
        size_t maxAllowed = maxSize_ + elasticity_;
        if (maxSize_ == 0 || cache_.size() < maxAllowed) {
            return 0;
        }
        size_t count = 0;
        while (cache_.size() > maxSize_) {
            cache_.erase(entries_.back().key);
            entries_.pop_back();
            ++count;
        }
        return count;
    }

   private:
    // Disallow copying.
    Cache(const Cache&) = delete;
    Cache& operator=(const Cache&) = delete;

    Map cache_;
    list_type entries_;
    size_t maxSize_;
    size_t elasticity_;
};
}  // namespace common

#endif  // COMMON_CACHE_LRU_CACHE_H