#ifndef ADDITIONAL_DATA_H
#define ADDITIONAL_DATA_H

//#ifndef SWIGPYTHON

#include "Header.hh"
#include "ElementContainer.hh"
#include "ElementContainerArray.hh"

#include "AdvMessage.hh"
#include "AdvDomain.hh"
#include "AdvParamSet.hh"
#include "AdvFuncBase.hh"
#include "AdvFuncComb.hh"
#include "AdvLevmarConsts.hh"
#include "AdvLevmarControl.hh"

/** function to evaluate the values and the Jacobi matrix for fitting
 *
 *  the lower and the upper bounds of the domain
 *  the x coordinates where the values of the fitting function are evaluated in the domain
 *  the weights for evaluated values at x ccordinates
 */
class AdvFuncEvalBase : public AdvMessage {
    private:
        static const string className; // = string("FuncEvalBase");
    public:
        /** a list of primitive functions */
        AdvFuncComb *f;
        //vector<AdvFuncBase*> *funcList;
        /** bounds of the domain */
        vector<Double> bounds;
        /** coordinates for the objective function */
        vector<Double> *x;
        /** weight for reference data */
        vector<Double> *w;

    public:
        AdvFuncEvalBase();
        AdvFuncEvalBase(Bool useWeight, UInt4 nSeries, vector<AdvFuncBase*> &funcList, ElementContainer &src, AdvDomain &domain);
        AdvFuncEvalBase(Bool useWeight, UInt4 nSeries, vector<AdvFuncBase*> &funcList, ElementContainer &src, AdvDomain &domain, vector<Double>p);
        ~AdvFuncEvalBase();

        Bool check() ;
        void set(vector<Double> &patam);
        vector<Double> *getDomainBounds();
        vector<Double> eval();
        vector< vector<Double> > gradient();
        void eval(Int4 n, Double y[]);
        void evalJacobi(Int4 n, Double jac[]);
};


/** functions to evaluate the values and the Jacobi matrix for fitting function(s)
 */
class AdvAdditionalData :public AdvMessage {

    private:
        static const string className; // = string("AdvAdditionalData");

    public:
        /** use weight */
        Bool useWeight;
        /** the number of function list */
        UInt4 nSeries;
        /** elemental data for function's falue and Jacobian */
        vector<AdvFuncEvalBase> *funcEvalBaseList;

        Double *linklist;

    public:
        AdvAdditionalData(AdvLevmarControl &control,  ElementContainer      &src,  AdvDomain         &domain,  AdvParamSet &paramSet);
        AdvAdditionalData(AdvLevmarControl &control,  ElementContainerArray &src,  vector<AdvDomain> &domain,  AdvParamSet &paramSet);
        ~AdvAdditionalData();

        Bool            empty() const;
        Bool            check();
        UInt4           getNumberOfSeries() const;

        AdvFuncComb       *getFunc(UInt4 i);
        UInt4           getNumberOfData(UInt4 i) const;
        vector<Double> *getDomainBounds(UInt4 i) const;
        vector<Double> *getX(UInt4 i);
        vector<Double> *getWeight(UInt4 i);

        void set(vector<Double> &param);
        void eval(Int4 n, Double *v);
        void evalJacobian(Int4 n, Int4 nParam, Double *j);
        void output(UInt4 indent);
};

//#endif //  SWIGPYTHON

#endif // ADDITIONAL_DATA_H
