#ifndef FUNC_COMB_TO_ELEMENT_CONTAINER
#define FUNC_COMB_TO_ELEMENT_CONTAINER

#include <stdexcept>

#include "Header.hh"
#include "ElementContainer.hh"
#include "CppToPython.hh"
#include "StringTools.hh"

#include "AdvFuncComb.hh"

/** evaluates the values of the linear combination of the built-in functions and returns the results as an ElementContainer
 *
 * @author TANIMORI Souichirou, AdvanceSoft Corp.
 * @version 0.0
 * @sice    0.0
 */
class AdvFuncCombToElementContainer : public AdvFuncComb {
    private:
        /** class name */
        static const string className; // = string("AdvFuncCombToElementContainer ");

    public:
        /** constructor */
        AdvFuncCombToElementContainer() {};

        /** constructor
         *  @param[in] funcList   a list of built-in functions
         *  @param[in] paramList  a list of parameters for the functions
         */
        AdvFuncCombToElementContainer(const vector<AdvFuncBase*>& funcList, const vector<Double>& paramList) : AdvFuncComb(funcList, paramList) {};

        /** constructor
         *  @param[in] funcList      a list of built-in functions
         *  @param[in] paramList     a list of parameters for the functions
         *  @param[in] paramErrList  a list of parameter errors for the functions
         */
        AdvFuncCombToElementContainer(const vector<AdvFuncBase*>& funcList, const vector<Double>& paramList, const vector<Double>& paramErrList) : AdvFuncComb(funcList, paramList, paramErrList) {};

        /** constructor
         *  @param[in] expr       a string expression for function list
         *  @param[in] paramList  a python list of parameters for the functions
         */
        AdvFuncCombToElementContainer(const string& expr, PyObject* paramList) : AdvFuncComb(expr, paramList) {};

        /** constructor
         *  @param[in] expr          a string expression for function list
         *  @param[in] paramList     a python list of parameters for the functions
         *  @param[in] paramErrList  a python list of parameter errors for the functions
         */
        AdvFuncCombToElementContainer(const string& expr, PyObject* paramList, PyObject* paramErrList) : AdvFuncComb(expr, paramList, paramErrList) {};

        /** destructor */
        ~AdvFuncCombToElementContainer() {};

        /** evaluate functions and returns the results as ElementContainer
         *  @param[in] xkey  the key for bins
         *  @param[in] ykey  the key for values
         *  @param[in] ekey  the key for errors
         *  @param[in] xunit the unit for bins
         *  @param[in] yunit the unit for values
         *  @param[in] bins  bins (domain) in order to evaluate the values of the linear combination of built-in functions
         *  @param[in] c     ratio for internally dividing point beteen two adjacent bin points.
         *                   the values are evaluated at the points. 0.0 &le; c &lt; 1.0, the default value is 0.5.
         */
        ElementContainer create(const string& xkey, const string& ykey, const string& ekey, const string& xunit, const string& yunit, const vector<Double>& bins, const Double c = 0.5);

        /** evaluate functions and returns the results as ElementContainer
         *  @param[in] keys  a list of key strings. the list must have three elements.
         *  @param[in] units a list of unit strings. the list must have two elements.
         *  @param[in] bins  bins (domain) in order to evaluate the values of the linear combination of built-in functions
         *  @param[in] c     ratio for internally dividing point beteen two adjacent bin points.
         *                   the values are evaluated at the points. 0.0 &le; c &lt; 1.0, the default value is 0.5.
         */
        ElementContainer create(const vector<string>& keys, const vector<string>& units, const vector<Double>& bins, const Double c = 0.5);

        /** evaluate functions and returns the results as ElementContainer
         *  @param[in] xkey  the key for bins
         *  @param[in] ykey  the key for values
         *  @param[in] ekey  the key for errors
         *  @param[in] xunit the unit for bins
         *  @param[in] yunit the unit for values
         *  @param[in] bins  bins (domain) in order to evaluate the values of the linear combination of built-in functions
         *  @param[in] c     ratio for internally dividing point beteen two adjacent bin points.
         *                   the values are evaluated at the points. 0.0 &le; c &lt; 1.0, the default value is 0.5.
         */
        ElementContainer create(const string& xkey, const string& ykey, const string& ekey, const string& xunit, const string& yunit, PyObject* bins, const Double c = 0.5);

        /** evaluate functions and returns the results as ElementContainer
         *  @param[in] keys  a python list of key strings. the list must have three elements.
         *  @param[in] units a python list of unit strings. the list must have two elements.
         *  @param[in] bins  bins (domain) in order to evaluate the values of the linear combination of built-in functions
         *  @param[in] c     ratio for internally dividing point beteen two adjacent bin points.
         *                   the values are evaluated at the points. 0.0 &le; c &lt; 1.0, the default value is 0.5.
         */
        ElementContainer create(PyObject* keys, PyObject* units, PyObject* bins, const Double c=0.5);
};
#endif // FUNC_COMB_TO_ELEMENT_CONTAINER
