// Copyright 2017 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef DEVTOOLS_GOMA_CLIENT_LINKED_UNORDERED_MAP_H_
#define DEVTOOLS_GOMA_CLIENT_LINKED_UNORDERED_MAP_H_

#include <list>
#include <unordered_map>

#include "glog/logging.h"

namespace devtools_goma {

// LinkedUnorderedMap is an unordered map, which keeps insertion order.
//
// Note: Unfortunately, this implementation prohibits from using move-only type
// in key, since key will be copied to list and map.
//
// This is not thread-safe.
template<typename K, typename V, typename H = std::hash<K>>
class LinkedUnorderedMap {
 public:
  using ListType = std::list<std::pair<K, V>>;
  using MapType = std::unordered_map<K, typename ListType::iterator, H>;
  using const_iterator = typename ListType::const_iterator;
  using iterator = typename ListType::iterator;

  size_t size() const {
    DCHECK_EQ(map_.size(), list_.size());
    return list_.size();
  }
  bool empty() const { return list_.empty(); }

  const std::pair<K, V>& front() const {
    DCHECK(!empty());
    return list_.front();
  }

  void pop_front();
  // This overwrites the previous entry if key is registered.
  // Note: To use universal reference, this method is template.
  // TODO: Aligh interface with std container.
  template<typename KK, typename VV>
  void emplace_back(KK&& k, VV&& v);

  // Move the value which iterator points to the last.
  void MoveToBack(iterator it);

  iterator begin() { return list_.begin(); }
  const_iterator begin() const { return list_.begin(); }
  iterator end() { return list_.end(); }
  const_iterator end() const { return list_.end(); }

  iterator find(const K& key);
  const_iterator find(const K& key) const;

 private:
  // Implementation Note: std::list iterator does not die after inserting
  // or deleting an entry. So, it is safe to have an list iterator in |map_|.
  ListType list_;
  MapType map_;
};

template<typename K, typename V, typename H>
void LinkedUnorderedMap<K, V, H>::pop_front() {
  DCHECK(!empty());
  map_.erase(list_.front().first);
  list_.pop_front();
}

template<typename K, typename V, typename H>
template<typename KK, typename VV>
void LinkedUnorderedMap<K, V, H>::emplace_back(KK&& key, VV&& value) {
  auto map_it = map_.find(key);
  if (map_it == map_.end()) {
    // key cannot be moved here. used later.
    list_.emplace_back(key, std::forward<VV>(value));
    auto back_it = list_.end();
    --back_it;
    map_.insert(make_pair(std::forward<KK>(key), back_it));
  } else {
    list_.erase(map_it->second);
    list_.emplace_back(std::forward<KK>(key), std::forward<VV>(value));
    auto back_it = list_.end();
    --back_it;
    map_it->second = back_it;
  }
}

template<typename K, typename V, typename H>
void LinkedUnorderedMap<K, V, H>::MoveToBack(
    typename LinkedUnorderedMap<K, V, H>::iterator it) {
  list_.splice(list_.end(), list_, it);
}

template<typename K, typename V, typename H>
typename LinkedUnorderedMap<K, V, H>::iterator
LinkedUnorderedMap<K, V, H>::find(const K& key) {
  auto it = map_.find(key);
  if (it == map_.end()) {
    return list_.end();
  }

  return it->second;
}

template<typename K, typename V, typename H>
typename LinkedUnorderedMap<K, V, H>::const_iterator
LinkedUnorderedMap<K, V, H>::find(const K& key) const {
  auto it = map_.find(key);
  if (it == map_.end()) {
    return list_.end();
  }

  return it->second;
}

}  // namespace devtools_goma

#endif  // DEVTOOLS_GOMA_CLIENT_LINKED_UNORDERED_MAP_H_
