/*
$Id: StlMapDouble.hh 2247 2011-04-27 05:20:41Z jisuzuki $
*/


#ifndef STLMAPDOUBLE
#define STLMAPDOUBLE

/* Header.hh should be included on the top to avoid environments
 * specific issues (see Header.hh for the detail).
 */
#include "Header.hh"

#include <map>
#include <algorithm>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/map.hpp>


class StlMapDouble{
private:
  std::map< std::string, std::vector<Double> > M;

  const std::vector<Double>* PutPointer( const std::string &key ) const {
    return &ref(key);
  }
  //!< @return a pointer to the vector which has stored with the specified key
  // (pointed vector is treated as const; it is useful to used from const methods

  std::vector<Double>* PutPointer( const std::string &key ) {
    return const_cast<std::vector<Double>* >(
      static_cast<const StlMapDouble &>(*this).PutPointer( key )); };
  //!< @return a pointer to the vector; it is not const

  const std::vector<Double>* PutPointer( UInt4 index ) const;
  std::vector<Double>* PutPointer( UInt4 index ) {
    return const_cast<std::vector<Double>* >(
      static_cast<const StlMapDouble &>(*this).PutPointer( index )); };

  const std::vector<Double>* operator()( const std::string &key ) const { return PutPointer( key ); }
  const std::vector<Double>* operator()( UInt4 index ) const { return PutPointer( index ); }

  std::vector<Double>* operator()( const std::string &key ) { return PutPointer( key ); }
  std::vector<Double>* operator()( UInt4 index ) { return PutPointer( index ); }


  /** ref() a reference implementation of the operator[] for this class
   *
   * operator() and PutPointer() are to be replaced by this method
   * @param key a key to a vector
   * @return reference to a vector
   */
  std::vector<Double> &ref(const std::string &key) { return M[key]; };

  /** ref() a reference implementation of the operator[] for this class
   *
   * operator() and PutPointer() are to be replaced by this method
   * @param key a key to a vector
   * @return const reference to a vector
   */
  const std::vector<Double> &ref(const std::string &key) const;


  friend class boost::serialization::access;
  /** serialize method used from boost::serialization::access
   *
   */
  template <class Archive>
  void serialize(Archive &ar, const unsigned int ver);

protected:

public:
  StlMapDouble();
 ~StlMapDouble();
  void clear(){ M.clear(); }

  StlMapDouble( const StlMapDouble &ob );
  StlMapDouble &operator=( const StlMapDouble &ob );

  void Append( const std::string &key, std::vector<Double> &value );
  void Add( const std::string &key, std::vector<Double> &value ){ Append( key, value ); }
/*
  void AppendP( std::string key, std::vector<Double> *value );
  void AddP( std::string key, std::vector<Double> *value ){ AppendP( key, value ); }
*/
  std::vector<Double> &Put( const std::string &key );
  std::vector<Double> &Put( UInt4 index );

  void Erase( const std::string &key );
  void Delete( const std::string &key ){ Erase( key ); }
  void Replace( const std::string &key, std::vector<Double> &value );
  void Copy( const std::string &OldKey, const std::string &NewKey );
  UInt4 CheckKey( const std::string &key ){
    if( M.find( key ) == M.end() ) return 0; else return 1;
  };

  //! reverse all std::vector
  void Reverse() {
    for (std::map< std::string, std::vector<Double> >::iterator p=M.begin(),
         end=M.end();p!=end;++p)
      std::reverse((*p).second.begin(), (*p).second.end());
  }

  //! @return the number of std::vector stored in this object
  UInt4 Size() const { return (UInt4)M.size(); }

  //! @return the size of std::vector which has the key
  UInt4 Size(const std::string &key) const {
    std::map< std::string, std::vector<Double> >::const_iterator R = M.find( key );
    return (UInt4)R->second.size();}

  std::vector<std::string> PutKeyList();
  void DumpKeyList();

  Int8 PutIndexNumber( const std::string &Key );
  /*!< @brief
    The speed of this method is very slow,
    I do not recommend to use this method.

    This method will return -1, when Key is not
    registered in this std::map.
  */

  friend class ElementContainer;
};
template <class Archive>
void StlMapDouble::
serialize(Archive &ar, const unsigned int ver) {
  ar & boost::serialization::make_nvp("STLMapDouble", M);
}


/*
 *
 * StlMapDouble doesn't have NXwrite and NXread
 * because ElementContainer write and read std::map<std::string, std::vector<double> >
 * to/from NeXus file directly
 */
#endif
