// -*- C++ -*- //
#ifndef HUGO_MAPS_H
#define HUGO_MAPS_H

///\file
///\brief Miscellaneous property maps
///
///\todo This file has the same name as the concept file in skeletons,
/// and this is not easily detectable in docs...

#include <map>

namespace hugo {

  /// Null map. (aka DoNothingMap)

  /// If you have to provide a map only for its type definitions,
  /// or if you have to provide a writable map, but will not use the
  /// data written to it...
  template<typename K, typename T>
  class NullMap
  {
  public:
    typedef K KeyType;
    typedef T ValueType;

    T operator[](const K&) const { return T(); }
    void set(const K&, const T&) {}
  };


  /// Constant map.

  /// This is a readable map which assignes a specified value to each key.
  /// In other aspects it is equivalent to the \ref NullMap
  template<typename K, typename T>
  class ConstMap
  {
    T v;
  public:
    typedef K KeyType;
    typedef T ValueType;

    ConstMap() {}
    ConstMap(const T &_v) : v(_v) {}

    T operator[](const K&) const { return v; }
    void set(const K&, const T&) {}

    template<typename T1>
    struct rebind {
      typedef ConstMap<K,T1> other;
    };

    template<typename T1>
    ConstMap(const ConstMap<K,T1> &, const T &_v) : v(_v) {}
  };



  /// \c std::map wrapper

  /// This is essentially a wrapper for \c std::map. With addition that
  /// you can specify a default value different from \c ValueType() .
  ///
  /// \todo Provide allocator parameter...
  template <typename Key, typename T, typename Compare = std::less<Key> >
  class StdMap : public std::map<Key,T,Compare> {
    typedef std::map<Key,T,Compare> parent;
    T v;
    typedef typename parent::value_type PairType;

  public:
    typedef Key KeyType;
    typedef T ValueType;
    typedef T& ReferenceType;
    typedef const T& ConstReferenceType;


    StdMap() : v() {}
    /// Constructor with specified default value
    StdMap(const T& _v) : v(_v) {}

    /// \brief Constructs the map from an appropriate std::map.
    ///
    /// \warning Inefficient: copies the content of \c m !
    StdMap(const parent &m) : parent(m) {}
    /// \brief Constructs the map from an appropriate std::map, and explicitly
    /// specifies a default value.
    ///
    /// \warning Inefficient: copies the content of \c m !
    StdMap(const parent &m, const T& _v) : parent(m), v(_v) {}
    
    template<typename T1, typename Comp1>
    StdMap(const StdMap<Key,T1,Comp1> &m, const T &_v) { 
      //FIXME; 
    }

    ReferenceType operator[](const Key &k) {
      return insert(PairType(k,v)).first -> second;
    }
    ConstReferenceType operator[](const Key &k) const {
      typename parent::iterator i = lower_bound(k);
      if (i == parent::end() || parent::key_comp()(k, (*i).first))
	return v;
      return (*i).second;
    }
    void set(const Key &k, const T &t) {
      parent::operator[](k) = t;
    }

    /// Changes the default value of the map.
    /// \return Returns the previous default value.
    ///
    /// \warning The value of some keys (which has alredy been queried, but
    /// the value has been unchanged from the default) may change!
    T setDefault(const T &_v) { T old=v; v=_v; return old; }

    template<typename T1>
    struct rebind {
      typedef StdMap<Key,T1,Compare> other;
    };
  };
  
}
#endif // HUGO_MAPS_H
