#ifndef FUNCBASE_H
#define FUNCBASE_H 1

#include <string>
#include "Header.hh"

//#define USE_POINTER
#define USE_VECTOR
//#define USE_SETTER_GETTER

#define HAVE_DIFFERENTIAL_MEMBER

class AdvFuncBase {
    private:
        /** the number of parameters p for the functions f(x; p) */
        UInt4 nParam;
        /** the name of the functions */
        string name;
        /** the esymbol of the functions */
        string symbol;
        /** a list of parameter's order
         *      height, peak position, HWHM etc.
         */
        //vector<string> paramNameList;
           

    public:
        /** default constructor */
        AdvFuncBase() ;
        /** constructor */
        AdvFuncBase(const string name, const string symbol, const UInt4 nParam);
        /** copy contructor */
        AdvFuncBase(const AdvFuncBase &obj);
        //AdvFuncBase(const string name, const string symbol, const UInt4 nParam, const string[] );

        /** destructor */
        virtual ~AdvFuncBase() ;

        /** set values */
        void set(const string name, const string symbol, const UInt4 nParam);

        /** output to stdout */
        void dump() const ;

        /** get the number of parameters */
        UInt4 getNumberOfParam() const ;
        /** get the name of the function */
        string getName() const ;
        /** get the symbol for the function */
        string getSymbol() const ;
        /** get a list of parameter names */
        //vector<string> getParamList();

#ifdef USE_POINTER
        /** evaluate the value of the function */
        virtual Double eval(const Double x, const Double *p) = 0 ;
#ifdef HAVE_DIFFERENTIAL_MEMBER
        /** evaluate the value of the 1st derivative function */
        virtual Double der1st(const Double x, const Double *p) = 0 ;
        /** evaluate the value of the 2nd derivative function */
        virtual Double der2nd(const Double x, const Double *p) = 0 ;
        /** evaluate the gradient of the function for parameters */
        virtual Double *gradient(const Double x, const Double *p) = 0;
#endif //HAVE_DIFFERENTIAL_MEMBER
#endif //USE_POINTER

#ifdef USE_VECTOR
        /** evaluate the value of the function */
        virtual Double eval(const Double x, const vector<Double> &p) = 0;
#ifdef HAVE_DIFFERENTIAL_MEMBER
        /** evaluate the value of the 1st derivative function */
        virtual Double der1st(const Double x, const vector<Double> &p) = 0;
        /** evaluate the value of the 2nd derivative function */
        virtual Double der2nd(const Double x, const vector<Double> &p) = 0;
        /** evaluate the gradient of the function for parameters */
        virtual vector<Double> gradient(const Double x, const vector<Double> &p) = 0;
#endif //HAVE_DIFFERENTIAL_MEMBER
#endif //USE_VECTOR

//#ifdef USE_SETTER_GETTER
//        virtual Double  eval(  const Double x) = 0;
//        virtual Double  der1st(const Double x) = 0;
//        virtual Double  der2nd(const Double x) = 0;
//#ifdef USE_POINTER
//        virtual void    setParam(const Double *p) = 0;
//        //virtual Double *getParam();
//        //virtual Double *gradient(const Double x);
//#endif  // USE_POINTER
//
//#ifdef USE_VECTOR
//        virtual void           setParam(const vector<Double> &p) = 0;
//        //virtual vector<Double> getParam();
//        //virtual vector<Double> gradient(const Double x);
//#endif  //  USE_VECTOR
//#endif
};

#endif
