#ifndef REPORT_CONVERGENCE_PROCESS
#define REPORT_CONVERGENCE_PROCESS

//#ifdef SWIGPYTHON
//class AdvReportConvergenceProcess;
//#else // SWIGPYTHON

#include <ostream>
#include <ios>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>

#include "Header.hh"
#include "ThreadBase.hh"

#include "AdvMatrixUtil.hh"
#include "AdvParamSet.hh"
#include "AdvLevmarConsts.hh"
#include "AdvLevmarImmutables.hh"
#include "AdvConvergenceStat.hh"

class AdvReportConvergenceProcess : public AdvMessage, public AdvMatrixUtil, public ThreadBase {
//class AdvReportConvergenceProcess : public Message, public MatrixUtil {

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

    private:
        AdvLevmarImmutables *im;
        AdvConvergenceStat *stat;
        AdvConvergenceStat *history;

        ios_base::fmtflags flags;
        
        Int4 indentWidth;
        Int4 intWidth;
        Int4 doublePrecision;
        Int4 doubleWidth;

    public:
        AdvReportConvergenceProcess(AdvLevmarImmutables *im, AdvConvergenceStat *stat, AdvConvergenceStat *history);
        ~AdvReportConvergenceProcess();

        void Run() ;

    private:
        void setStreamFlags();
        void resetStreamFlags();

        Int4 setIterationCount(const AdvParamSet *p);
        Double setRFactor(const AdvParamSet *p);
        Double setResidualErrNorm(const AdvParamSet *p);
        Double setGradientNorm(const AdvParamSet *p);
        Double setParamDiffNorm(const AdvParamSet *p);
        AdvLevmarConsts::LevmarStat setTerminationStat(const AdvParamSet *p);

        Double setMuRatio(const AdvParamSet *p) const ;
        Int4 setFunctionEvaluations(const AdvParamSet *p) const ;
        Int4 setJacobianEvaluations(const AdvParamSet *p) const ;
        Int4 setLinearSystemsSolved(const AdvParamSet *p) const ;
        Int4 setIterationTime(const AdvParamSet *p) const ;

        vector<Double> setParameterValues(const AdvParamSet *p) const ;

        void outputConvergenceProcessHeader();
        void outputStat(const AdvParamSet *p);
        void outputConvergenceProcess();

        void outputTerminationStat(const AdvParamSet *p);
        void outputFittedParam(const AdvParamSet *p);
        void outputCovarianceMatrix(const AdvParamSet *p);
        void outputConvergenceHistory();
        void outputResult();
};

//#endif //  SWIGPYTHON

#endif // REPORT_CONVERGENCE_PROCESS
