/*
$Id: ElementContainerArray.hh 2295 2011-08-10 02:57:13Z jisuzuki $
*/


#ifndef ELEMENTCONTAINERARRAY
#define ELEMENTCONTAINERARRAY

//#include <stdio.h>
//#include <stdlib.h>

#include "Header.hh"
#include "NeutronVector.hh"
#include "ElementContainer.hh"
#include "NeutronReadBinaryData.hh"
#include "NeutronWriteBinaryData.hh"
#include "CppToPython.hh"
#include "ElementContainerAppendError.hh"

//! Data container for a set of ElementContainer-s and HeaderBase.
/*!
  This class is inherited from the template class,
  NeutronVector<ElementContainer,HeaderBase>.
  This class is a Data-container class for storeing
  a set of ElementContainer-s and HeaderBase.
  See the manuals of the template class of NeutronVector<T,H>.
 */

class ElementContainerArray
  : public NeutronVector< ElementContainer, HeaderBase >
{
private:
  friend class ElementContainerMatrix;
  //!< to access to v from ElementContainerMatrix::AllSum()

public:
  using NeutronVector< ElementContainer, HeaderBase >::operator();

  ElementContainerArray();
  /*!< @brief Constructor.

  This method only calls
    the constructor of the base class.
   */
  ElementContainerArray( HeaderBase pheader );
  /*!< @brief Constructor.

  This method only calls
    the constructor of the base class.
   */

  ElementContainerArray( const NeutronVector< ElementContainer, HeaderBase > &ob );
  // This copy constructor is very important from operators in NeutronVector

  /*
  ElementContainerArray &operator=
  ( const ElementContainerArray &ob );
  */

  ElementContainerArray( const ElementContainerArray &ob );

  std::vector<Double>* operator()( UInt4 index, std::string key );
  /*!< @brief Returns the pointer of std::vector<Double> named as "key".

    The vector is extracted from the ElementContainer assined
    as "index". */
  std::vector<Double>*   operator()( UInt4 index, UInt4 C_index );
  /*!< @brief Returns the pointer of std::vector<Double> whose index number is "C_index".

    The vector is extracted from the ElementContainer assined
    as "index". */

  std::vector<UInt4> SaveToBinFile( std::string key, std::string FileName );
  /*!< @brief
    Histogram data stored in this class are saved
    as a file in binary data format.

    Histogram data are extracted from each ElementContainer with "key",
    and the dimension of ElementContainerArray is written in the
    type of std::vector<UInt4> and returned by this method.
    The return value will be used as the second argument of
    ReadBinFile(std::string,std::vector<UInt4>,std::string).
   */

  PyObject *SaveToBinFilePy( std::string key, std::string FileName );
  /*!< @brief
    This method has the same functionality as "SaveToBinFile(std::string,std::string)".

    The return value can be recognized by python-environment directory.
   */

  void ReadBinFile( std::string FileName, std::vector<UInt4> dimensions,
    std::string key );
  /*!< @brief
    Histogram data stored by SaveToBinFile(std::string,std::string) is read
    with this method, and rebuild ElementContainerArray.

    This method should be called just after constructing this
    class method. The binary data will be stored in each ElementContainer
    with "key".
   */

  void ReadBinFile( std::string FileName, PyObject *dimensions,
    std::string key );
  /*!< @brief
    This method has the same functionality
    as "ReadBinFile(std::string,PyObject*,std::string)".

    The second argument should be the return value of
    "SaveToBinFilePy(std::string,std::string)".
   */

  void AppendErr( std::string Counts, std::string Error, Double ErrorValue=0.0 );
  /*!< @brief
    This method appends a vector<Double> into each object of ElementContainer.

    The first argument is the key-name of neutron-counts, and
    the second is the key-name of its error-value created and appended
    by this method.
    The third argument is passed to the constructor of
    "ElementContainerAppendError", please see the manual of it.
   */

  ElementContainerArray Mul( Double d );
  ElementContainerArray &MulMySelf( Double d );
  ElementContainerArray Mul( Double d, Double e );
  ElementContainerArray &MulMySelf( Double d, Double e );
  ElementContainerArray Mul( std::pair<Double,Double> &p ){ return Mul(p.first,p.second); }
  ElementContainerArray &MulMySelf( std::pair<Double,Double> &p ){ return MulMySelf(p.first,p.second); }

  ElementContainerArray Plus( Double d );
  ElementContainerArray &PlusMySelf( Double d );
  ElementContainerArray Plus( Double d, Double e );
  ElementContainerArray &PlusMySelf( Double d, Double e );
  ElementContainerArray Plus( std::pair<Double,Double> &p ){ return Plus(p.first,p.second); }
  ElementContainerArray &PlusMySelf( std::pair<Double,Double> &p ){ return PlusMySelf(p.first,p.second); }

  ElementContainerArray Pow( Double d );
  ElementContainerArray &PowMySelf( Double d );
  ElementContainerArray MergeWithWeight( ElementContainerArray &eca );
};


#endif
