// Copyright 2017-2020 The Verible Authors.
//
// 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.

#ifndef VERIBLE_COMMON_UTIL_BIJECTIVE_MAP_H_
#define VERIBLE_COMMON_UTIL_BIJECTIVE_MAP_H_

#include <functional>
#include <initializer_list>
#include <map>
#include <utility>

#include "common/util/forward.h"
#include "common/util/logging.h"

namespace verible {

// 1-to-1 key-value map that maintains bijectiveness as an invariant.
// Both keys and values are stored once, and internal cross-reference
// maps point to each other's keys.
// Using std::map internally because it provides stable iterators
// across insertion/deletion operations.
template <class K, class V, class KComp = std::less<K>,
          class VComp = std::less<V>>
class BijectiveMap {
  // Map of keys to values (by pointer).
  // Would really rather have value_type be a reverse_map_type::const_iterator
  // but cannot due to mutually recursive template type.
  typedef std::map<K, const V*, KComp> forward_map_type;
  // Map of values to keys (by pointer).
  // Would really rather have value_type be a forward_map_type::const_iterator
  // but cannot due to mutually recursive template type.
  typedef std::map<V, const K*, VComp> reverse_map_type;

 public:
  BijectiveMap() = default;

  // Initializes from a pair of iterators (to key-value pairs).
  // Duplicate key or value entries will result in a fatal error.
  template <class Iter>
  BijectiveMap(Iter begin, Iter end) {
    for (; begin != end; ++begin) {
      CHECK(insert(*begin)) << "duplicate key or value: (" << begin->first
                            << ", " << begin->second << ')';
    }
  }

  // Initializes from a list of pairs.
  // Duplicate key or value entries will result in a fatal error.
  BijectiveMap(std::initializer_list<std::pair<K, V>> pairs)
      : BijectiveMap(pairs.begin(), pairs.end()) {}

  // Returns number of keys, which is same as number of values.
  size_t size() const { return forward_map.size(); }

  bool empty() const { return forward_map.empty(); }

  // read-only direct access to internal maps
  const forward_map_type& forward_view() const { return forward_map; }
  const reverse_map_type& reverse_view() const { return reverse_map; }

  // Lookup value given key.  Returns nullptr if not found.
  template <typename ConvertibleToKey>
  const V* find_forward(const ConvertibleToKey& k) const {
    const auto found = forward_map.find(k);
    return found == forward_map.end() ? nullptr : found->second;
  }

  // Lookup key given value.  Returns nullptr if not found.
  template <typename ConvertibleToValue>
  const K* find_reverse(const ConvertibleToValue& v) const {
    const auto found = reverse_map.find(v);
    return found == reverse_map.end() ? nullptr : found->second;
  }

  // Returns true if successfully inserted new pair.
  bool insert(const std::pair<K, V>& p) { return insert(p.first, p.second); }

  // Establishes 1-1 association between key and value.
  // Returns true if successfully inserted new pair.
  bool insert(const K& k, const V& v) {
    const auto fwd_p = forward_map.insert(std::make_pair(k, nullptr));
    const auto rev_p = reverse_map.insert(std::make_pair(v, nullptr));
    if (fwd_p.second && rev_p.second) {
      // cross-link
      // pointers are guaranteed to be stable across non-destructive map
      // mutations.
      fwd_p.first->second = &rev_p.first->first;
      rev_p.first->second = &fwd_p.first->first;
      return true;
    } else {  // either key or value already existed in respective set
      // undo any insertions
      if (fwd_p.second) {
        forward_map.erase(fwd_p.first);
      }
      if (rev_p.second) {
        reverse_map.erase(rev_p.first);
      }
      return false;
    }
  }

  // function f is a (lazy) value generator that is invoked only when the key
  // insertion succeeds.  Retries value insertion (calling generator) until
  // success.  If the range of values generated is small, this could result
  // in more frequent retries.  Use cases for this include randomizing generated
  // values, or using secondary hashes to avoid collisions.
  const V* insert_using_value_generator(const K& k, std::function<V()> f) {
    const auto fwd_p = forward_map.insert(std::make_pair(k, nullptr));
    if (!fwd_p.second) return fwd_p.first->second;  // key entry aleady exists
    do {
      const auto rev_p = reverse_map.insert(std::make_pair(f(), nullptr));
      if (rev_p.second) {  // successful value insertion
        // cross-link
        fwd_p.first->second = &rev_p.first->first;
        rev_p.first->second = &fwd_p.first->first;
        return fwd_p.first->second;
      }
    } while (true);
    // never reached
    return nullptr;
  }

  // TODO(fangism): erase()

 private:
  // Internal storage of keys, and pointers to values
  forward_map_type forward_map;
  // Internal storage of values, and pointers to keys
  reverse_map_type reverse_map;
};

// TODO(fangism): forward and reverse view adaptors

}  // namespace verible

#endif  // VERIBLE_COMMON_UTIL_BIJECTIVE_MAP_H_
