#ifndef PEAK_FIT_H
#define PEAK_FIT_H

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

/**
 *
 */
class AdvPeakFit : virtual public AdvOperationBase {
    private:
        static const string className; // = string("AdvPeakFit");

    public:
        /**
         *  constructor
         */
        AdvPeakFit();

        AdvPeakFit(ElementContainer *src);
#ifndef SWIGPYTHON
        AdvPeakFit(ElementContainer *src, AdvMethod           *method);
#endif
        AdvPeakFit(ElementContainer *src, const AdvMethodType &methodType);
        AdvPeakFit(ElementContainer *src, const string     &methodName);

        /**
         *  constructor
         */
#ifndef SWIGPYTHON
        AdvPeakFit(ElementContainer *src, AdvMethod           *method,     const Double xLower, const Double xUpper);
#endif
        AdvPeakFit(ElementContainer *src, const AdvMethodType &methodType, const Double xLower, const Double xUpper);
        AdvPeakFit(ElementContainer *src, const string     &methodName, const Double xLower, const Double xUpper);

        /**
         *  constructor
         */
#ifndef SWIGPYTHON
        AdvPeakFit(ElementContainer *src, AdvMethod           *method,     const UInt4 lower, const UInt4 upper);
#endif
        AdvPeakFit(ElementContainer *src, const AdvMethodType &methodType, const UInt4 lower, const UInt4 upper);
        AdvPeakFit(ElementContainer *src, const string     &methodName, const UInt4 lower, const UInt4 upper);

        /**
         *  destructor
         */
        ~AdvPeakFit();

        /**
         *  execute peak fit
         */
        void execute();

        /**
         *  begin to fit
         */
        void fit() { this->method->toInnerForm(*(this->source), this->domain, this->param); this->method->fit(); };

        /**
         *  @retval true if fitting does not finish
         */
        Bool isFitting() { return this->method->isFitting(); };

        /**
         *  stop to fit
         */
        void stopFit() { this->method->stopFit(); }

        /**
         *  evaluate the values of functions
         */
        void eval() { this->method->eval(); };


        Double chiSq();

        AdvParamSet *getLatestConvergenceStat() const ;


        /** get evaluated values of fitting function for single data fitting as ElementContainer.
         */
       ElementContainer getResult();

        /** get evaluated values of fitting functions for  multiple data fitting as ElementContainerArray.
         */
       //ElementContaierArray getResultArray();

       /** get evaluated values of component functions for single data fitting as ElementContainerArray
        *
        */
       ElementContainerArray getResultComponents();

};

#endif
