#ifndef AdvParamSet_h
#define AdvParamSet_h

#include <string.h>
#include <list>
#include <map>
#include <string>
#include <cstdio>
#include <ios>
#include <ostream>
#include <iomanip>
#include <stdexcept>

#include "Header.hh"
#include "CppToPython.hh"

#include "AdvMessage.hh"
#include "AdvPeakData.hh"
#include "AdvFuncBase.hh"



/** 
 *  container for Double type matrix
 *
 *  \author TANIMORI Souichirou, AdvanceSoft Corp.
 *  \version 0.0
 *  \sinse   2.1.14
 */
class AdvParamSet : public AdvMessage {
 private:
    static const std::string className; // = std::string(AdvParamSet);

 private:

    /**
     *  container for Bool type parameters
     */
    std::map<std::string, Bool> BoolMap;

    /** 
     *  container for Int4 type parameters
     */
    std::map<std::string, Int4> Int4Map;

    /**
     *  container for UInt4 type parameters
     */
    std::map<std::string, UInt4> UInt4Map;

    /** 
     *  container for Double type parameters
     */
    std::map<std::string, Double> DoubleMap;

    /** 
     *  container for Double type vectors/array
     */
    std::map<std::string, std::vector<Double> > vectorMap;

    /** 
     *  container for Double tpye matrices
     */
    std::map<std::string, std::vector< std::vector<Double> > > matrixMap;


    /**
     *  container for PeakData
     */
    std::map<std::string, AdvPeakData> peakDataMap;

    /**
     * list  function
     */
    std::map<std::string, std::vector<AdvFuncBase*> > funcListMap;

    /**
     * list of function lists
     */
    std::map<std::string, std::vector< std::vector<AdvFuncBase*> > > funcMatrixMap;



 public:
    /**  default constructor */
    AdvParamSet();


    /**  destructor */
    ~AdvParamSet();


    /**  add a Bool type parameter with its key */
    void add(const std::string key, const Bool value);

    /**  add a Int4 type parameter with its key */
    void add(const std::string key, const Int4 value);

    /**  add a UInt4 type parameter with its key */
    void add(const std::string key, const UInt4 value);

    /**  add a Double type parameter with its key */
    void add(const std::string key, const Double value);

    /**  add a Double type std::vector with its key */
    void add(const std::string key, std::vector<Double> &value);

    void add(const std::string key, PyObject *value);

    /**  add a Double type matrix wthe its key */
    void add(const std::string key, std::vector< std::vector<Double> > value);

    /**  add a PeakData type parameter with key */
    void add(const std::string key, AdvPeakData peakData);

    void add(const std::string key, std::vector<AdvFuncBase*>);

    void add(const std::string key, std::vector< std::vector<AdvFuncBase*> >);

    /**  erase the data with the given key */
    void erase(const std::string &key);

    /**  replace the value of the Bool type data with the given key */
    void replace(const std::string &key, const Bool value);

    /**  replace the value of the Int4 type data with the given key */
    void replace(const std::string &key, const Int4 value);

    /**  replace the value of the UInt4 type data with the given key */
    void replace(const std::string &key, const UInt4 value);

    /**  replace the value of the Double type data with the given key */
    void replace(const std::string &key, const Double value);


    /**  replace the value of the Double type std::vector/array with the given key */
    void replace(const std::string &key, std::vector<Double> value);

    void replace(const std::string &key, PyObject *value);

    /**  replace the specified component of the vector with key */
    void replace(const std::string &key, const UInt4 i, const Double value);


    /**  replace the value of the Double type matrix with the given key */
    void replace(const std::string &key, std::vector< std::vector<Double> > value);

    /**  replace the specified component of the matrix with key */
    void replace(const std::string &key, UInt4 i, UInt4 j, Double value);

    /**  replace PeakData type parameter with key */
    void replace(const std::string &key, AdvPeakData value);

    /** replace the function list with the given key */
    void replace(const std::string &key, std::vector<AdvFuncBase*> value);

    /** replace the specified component of the function list with given key */
    void replace(const std::string &key, const UInt4 i, AdvFuncBase *value);

    void replace(const std::string &ket, std::vector< std::vector<AdvFuncBase*> > value) ;

    void replace(const std::string &key, UInt4 i, UInt4 j, AdvFuncBase *value);

    /**  dump the set of parameters to stdout */
    void dump();

    /** true if no data is registed */
    Bool empty() const ;

    /**  get the value of the Bool type data with the given key */
    Bool getBool(const std::string &Key) const ;


    /**  get the value of the Int4 type data with the given key */
    Int4 getInt4(const std::string &key) const ;

    /**  get the value of the UInt4 type data with the given key */
    UInt4 getUInt4(const std::string &key) const ;

    /**  get the value of the Double type data with the given key */
    Double getDouble(const std::string &key) const ;

    /**  get the Double type  std::vector with the given key */
    std::vector<Double> getVector(const std::string &key) const ;

    /**  get the value of the specified component of the Double type  std::vector with the given key */
    Double getDouble(const std::string &key, const UInt4 i) const ;

    /** get size of value with specified key */
    UInt4 getVectorSize(const std::string &key) const ;

    /**  get the Double type  matrix with the given key */
    std::vector< std::vector<Double> > getMatrix(const std::string &key) const ;

    /**  get the value of the specified component (i,j) of the Double type matrix with the given key */
    Double getDouble(const std::string &key, UInt4 i, UInt4 j) const ;

    /**  get the size of the row of the matrix with key */
    UInt4 getRowSize(const std::string &key) const ;

    /**  get the size of column of the matrix with key */
    UInt4 getColumnSize(const std::string &key) const ;

    /**  get the value of PeakData type paarameter with the given key. */
    AdvPeakData getPeakData(const std::string &key) const ;

    /** get a list of functions */
    std::vector<AdvFuncBase*> getFuncList(const std::string &key) const ;

    /** get a pointer to a list of functions */
    std::vector<AdvFuncBase*> *getFuncListP(const std::string &key) const ;

    std::vector< std::vector<AdvFuncBase*> > getFuncMatrix(const std::string &key) const ;

    /**  return a list of keys registed */
    std::vector<std::string> getKeyList() const ;

    /**  key (and the value(s) for the parameter with the key) is contained the param set */
    Bool contain(const std::string &key) const ;

};

#endif // Manyo_develop_operation_AdvParamSet_h

