#ifndef VTR_BIMAP
#define VTR_BIMAP
#include <map>
#include <unordered_map>
#include "vtr_flat_map.h"
#include "vtr_linear_map.h"

#include "vtr_error.h"

namespace vtr {

/*
 * A map-like class which provides a bi-directonal mapping between key and value
 *
 * Keys and values can be looked up directly by passing either the key or value.
 * the indexing operator will throw if the key/value does not exist.
 */
template<class K, class V, template<typename ...> class Map=std::map, template<typename ...> class InvMap=std::map>
class bimap {
    public: //Public types
        typedef typename Map<K,V>::const_iterator iterator;
        typedef typename InvMap<V,K>::const_iterator inverse_iterator;
    public: //Accessors

        //Iterators
        iterator begin() const { return map_.begin(); }
        iterator end() const { return map_.end(); }
        inverse_iterator inverse_begin() const { return inverse_map_.begin(); }
        inverse_iterator inverse_end() const { return inverse_map_.end(); }

        //Return an iterator to the key-value pair matching key, or end() if not found
        iterator find(const K key) const {
            return map_.find(key);
        }

        //Return an iterator to the value-key pair matching value, or inverse_end() if not found
        inverse_iterator find(const V value) const {
            return inverse_map_.find(value);
        }

        //Return an immutable reference to the value matching key
        //Will throw an exception if key is not found
        const V& operator[] (const K key) const {
            auto iter = find(key);
            if(iter == end()) {
                throw VtrError("Invalid bimap key during look-up", __FILE__, __LINE__);
            }
            return iter->second;
        }

        //Return an immutable reference to the key matching value
        //Will throw an exception if value is not found
        const K& operator[] (const V value) const {
            auto iter = find(value);
            if(iter == inverse_end()) {
                throw VtrError("Invalid bimap value during inverse look-up", __FILE__, __LINE__);
            }
            return iter->second;
        }

        //Return the number of key-value pairs stored
        std::size_t size() const { VTR_ASSERT(map_.size() == inverse_map_.size()); return map_.size(); }

        //Return true if there are no key-value pairs stored
        bool empty() const { return (size() == 0); }

        //Return true if the specified key exists
        bool contains(const K key) const { return find(key) != end(); }

        //Return true if the specified value exists
        bool contains(const V value) const { return find(value) != inverse_end(); }

    public: //Mutators

        //Drop all stored key-values
        void clear() { map_.clear(); inverse_map_.clear(); }

        //Insert a key-value pair, if not already in map
        std::pair<iterator,bool> insert(const K key, const V value) {
            auto ret1 = map_.insert({key,value});
            auto ret2 = inverse_map_.insert({value,key});

            VTR_ASSERT(ret1.second == ret2.second);

            //Return true if inserted
            return ret1;
        }

        //Update a key-value pair, will insert if not already in map
        void update(const K key, const V value) {
            map_[key] = value;
            inverse_map_[value] = key;
        }

        //Remove the specified key (and it's associated value)
        void erase(const K key) {
            auto iter = map_.find(key);
            if(iter != map_.end()) {
                V val = iter->second;
                map_.erase(iter);

                auto inv_iter = inverse_map_.find(val);
                VTR_ASSERT(inv_iter != inverse_map_.end());
                inverse_map_.erase(inv_iter);
            }
        }

        //Remove the specified value (and it's associated key)
        void erase(const V val) {
            auto inv_iter = inverse_map_.find(val);
            if(inv_iter != inverse_map_.end()) {
                K key = inv_iter->second;
                inverse_map_.erase(inv_iter);

                auto iter = map_.find(key);
                VTR_ASSERT(iter != map_.end());
                map_.erase(iter);
            }
        }

        //Swap (this enables std::swap via ADL)
        friend void swap(bimap<K,V,Map,InvMap>& x, bimap<K,V,Map,InvMap>& y) {
            std::swap(x.map_, y.map_);
            std::swap(x.inverse_map_, y.inverse_map_);
        }
    private:
        Map<K,V> map_;
        InvMap<V,K> inverse_map_;
};

template<class K, class V>
using unordered_bimap = bimap<K,V,std::unordered_map,std::unordered_map>;

template<class K, class V>
using flat_bimap = bimap<K,V,vtr::flat_map,vtr::flat_map>;

template<class K, class V>
using linear_bimap = bimap<K,V,vtr::linear_map,vtr::linear_map>;

}

#endif
