#ifndef AdvMultiDataMethod_h
#define AdvMultiDataMethod_h

#include "Header.hh"
#include "AdvDomain.hh"
#include "AdvParamSet.hh"
#include "ElementContainer.hh"
#include "ElementContainerArray.hh"
#include "ElementContainerMatrix.hh"



/** @author TANIMORI Souichirou, AdvanceSoft Corp.
     *  @version 0.0
     */
class AdvMultiDataMethod {

 protected:
    std::string methodName; // reffrence only afer initialising on construction

 protected:

    Double valueOfLikehood;


 protected:

     /**
      *  @return the value of the likehood for a method
      */
     virtual Double likehood()  = 0;

 public:

    ////////////////    constructor and destructor    ////////////////
    /** default constructor */
    AdvMultiDataMethod() ;

    /** constructor */
    AdvMultiDataMethod(const std::string name) { methodName=name; valueOfLikehood=0.0; };

    /** copy constructor */
    AdvMultiDataMethod(const AdvMultiDataMethod &method);

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

    ////////////////    operator    ////////////////
    /** assignement operator */
    AdvMultiDataMethod& operator = (const AdvMultiDataMethod &method) ;

    ////////////////    method specific information    ////////////////
    /** get the method name.
     */
    std::string getMethodName() const ;

    /**
     *  @retval true if the result function is analytically diffreantiable
     */
    virtual Bool differentiable() const = 0;


    /**
     *  @retval true if the Methosd supprot multi-thread processing
     */
    virtual Bool isMultiThreaded() const = 0;

    ////////////////    control method    ////////////////
    /**
     *  set default values of parameters
     *
     *  @param[in] src an element container as the source
     */
    virtual AdvParamSet setDefaultParam(ElementContainerArray &src) = 0;


    /** 
     *  check the parameters for the method before fitting and vevaluation
     *
     *  @param[in] src    element container as source
     *  @param[in] domain domain for the method
     *  @param[in] param  parameters for the method
     */
    virtual Bool checkParam( ElementContainerArray &src,  std::vector<AdvDomain> &domain,  AdvParamSet &param) = 0;

    /**
     *  translate parameters to inner form
     *
     *  @param[in] src    element container as source
     *  @param[in] domain domain for the method
     *  @param[in] param  parameters for the method
     */
    virtual void toInnerForm( ElementContainerArray &src,  std::vector<AdvDomain> &domain,  AdvParamSet &param)  = 0;


    /** 
     *  fit the parameters so that the the function reporduces the source
     */
    virtual void fit()  = 0;

    /**
     *  @retval true if fitting is not finished
     */
    virtual Bool isFitting() { return false ; };

    /**
     *
     */
    virtual void stopFit() {};


    /** 
     *  evaluate the values of the function in the domain
     */
    virtual void eval()  = 0;


    ////////////////    get results and data in progress    ////////////////

    /** export the  result for the i-th. fitting function (or data series) as ElementContainer.
     * @param[in]  src   the source for addtionan header data
     * @param[in]  id    the id No.  for the i-th. fitting function
     * @param[out] dest  the destination
     */
    virtual void toElementContainer(ElementContainerArray &src, UInt4 id, ElementContainer &dest) const = 0;

    /** export the  result as ElementContainerArray
     * @param[in]  src  the source for addtionan header data
     * @param[out] dest the destination
     */
    virtual void toElementContainerArray(ElementContainerArray &src, ElementContainerArray &dest) const = 0;


    /**
     * get the value of the likehood
     */
    Double getLikehood() const ;


    /** 
     *  get the fitted parameters
     */
    virtual AdvParamSet getFittedParam() const = 0;


    /** get the latest convergece stat.
     */
    virtual AdvParamSet *getLatestConvergenceStat() const = 0;

    /** get trend / increase and decrease table for the i-the fitting function.
     *
     *  table[0][i] : veluated value  of the fitted function at the i-th point/bin or the averaged value of histogram
     *  table[1][i] : 1st. derivative of the fitted function at the i-th point/bin or the averaged "1st. difference quatient"
     *  table[2][i] : 2nd. derivative of the fitted function at the i-th point/bin or the averaged "2nd. difference quatient"
     *
     * @param[in] id the id No. for the i-th. fitting functiond
     */
    virtual std::vector< std::vector<Double> > getTrend(UInt4 id) = 0 ;

    /** get trend / increase and decrease table for the all fitting function.
     *
     *  table[3*i+0][j] : evaluated value of the the i-th. fitted function at the j-th point/bin or the averaged value of histogram
     *  table[3*i+1][j] : 1st. derivative of the the i-th. fitted function at the j-th point/bin or the averaged "1st. difference quatient"
     *  table[3*i+2][j] : 2nd. derivative of the the i-th. fitted function at the j-th point/bin or the averaged "2nd. difference quatient"
     */
    virtual std::vector< std::vector<Double> > getTrend() = 0 ;

    ////////////////    parameter descriptions    ////////////////
    /** get the descriptions of parameters for the method.
     * @deprecated
     */
    virtual void getParamDescription() const  = 0;

};

#endif // Manyo_develop_operation_AdvMultiDataMethod_h

