#ifndef LEVMAR_CONSTS
#define LEVMAR_CONSTS

#include <cmath>
#include <cstdlib>
#include <pthread.h>

#include <exception>

/* headrs for levmar */
#include "compiler.h"
#include "levmar.h"
#include "lm.h"
#include "misc.h"

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

#include "AdvMessage.hh"
#include "AdvMethod.hh"
#include "AdvFuncBase.hh"

class AdvLevmarConsts {

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

    public:
        /** key for the kind of the constrain */
        static const std::string CONSTRAIN;          //=std::string("constrain");
        /** key for the flag of using the numerical differential Jaccobian */
        static const std::string USE_NUMERICAL_DIFF; //=std::string("use numerical diff");
        /** key for the method of numerical differentiation */
        static const std::string DIFF_METHOD;        //=std::string("diff method");
        /** ley for the flag of using data weight */
        static const std::string USE_DATA_WEIGHTS;  //=std::string("use data weights");

        /** key for maxmum iterations */
        static const std::string MAX_ITERATIONS;    //=std::string("max iteration");
        /** key for output interval */
        static const std::string OUTPUT_INTERVAL;    //=std::string("output interval");

        /** histroy depth */
        static const std::string HISTORY_CAPACITY; //=std::string("history capacity");


        /** key for fitting function */
        static const std::string FUNCTIONS;         //= std::string("function");

        /** keys for a set of initial values of fitting parameters */

        /** key for data mask */
        static const std::string MASK;

        /** key for initival values for fitting parameters */
        static const std::string INITIAL_PARAM_VALUES; //=std::string("initial param values");
        static const std::string PARAMETER_VALUES;   //=std::string("parameter values");
        static const std::string LINK_IDS;   //=std::string("link ids");

        /** key for a set of the refference data,
         * @ deprecated
         */
        static const std::string REFERENCE_VALUES;  //=std::string("reference values");

        /** keys for lower bound of box constrains */
        static const std::string LOWER_BOUNDS;     //=std::string("lower bound");
        /** keys for upper bound of box constrains */
        static const std::string UPPER_BOUNDS;     //=std::string("upper bound");
        /** key for weights of box constrains */
        static const std::string BOX_WEIGHTS;      //=std::string("box weight");
        /** key for linear equations */
        static const std::string EQUATIONS;        //=std::string("equations");
        /** key for linear inequalities */
        static const std::string INEQUALITIES;     //=std::string("inequalites");

        /** key for scaling factor */
        static const std::string SCALING_FACTOR;     //=std::string("scaling factor");
        /** key for threshold values for stopping conditions */
        /** \deprecated */
        static const std::string TOLERANCE;          //=std::string("tolerance");
        /** \deprecated */
        static const std::string RELATIVE_TOLERANCE; //=std::string("relatice tolerance");
        /** \deprecated */
        static const std::string GRADIENT_TOLERANCE; //=std::string("gradient tolerance");

        static const std::string RESIDU_ERR_THRESH;  //=std::string("residu. err. threshold")
        static const std::string GRADIENT_THRESH;    //=std::string("gradient threshold")
        static const std::string PARAM_DIFF_THRESH;  //=std::string("param. diff. threshold")

        /** key for step width for numerical differential Jaccobian */
        static const std::string DIFF_DELTA;         //=std::string("delta");

        /** iteration count */
        static const std::string ITERATION_COUNT;    //=std::string("iteration count");
        /** termination stat */
        static const std::string TERMINATION_STAT;   //=std::string("termination stat")
        /** key for R-factor */
        static const std::string R_FACTOR;           //=std::string("R factor");
        /** norm of residual error (L2) */
        static const std::string RESIDUAL_ERR_NORM;  //=std::string("residual error norm");
        /** norm of residual error (infinity) */
        static const std::string GRADIENT_NORM;      //=std::string("gradiend norm");
        /** norm of parameter difference (L2) */
        static const std::string PARAM_DIFF_NORM;    //=std::string("param. diff. norm");
        /** parameter errors */
        static const std::string PARAM_ERRORS;       //=std::string("param. errors");
        /** covariance matrix */
        static const std::string COVARIANCE_MATRIX;  //=std::string("param. errors");

        /** mu ratio i.e. mu/max{ [J^T J]_ii} */
        static const std::string MU_RATIO;              //=std::string("mu ratio");
        /** the number times of function evaluations */
        static const std::string FUNCTION_EVALUATIONS;  //=std::string("function evaluations")
        /** the number times of Jacobian evaluations */
        static const std::string JACOBIAN_EVALUATIONS;  //=std::string("Jacobian evaluations")
        /** the number times of linear systems solved */
        static const std::string LINEAR_SYSTEMS_SOLVED; //=std::string("linear systems solved")
        /** the time of iteration */
        static const std::string ITERATION_TIME;        //=std::string("iteration time")

        /** constrain for Levmar */
        enum Constrain {
            NO_CONSTRAIN, /* no constrain */
            BOX,          /* box */
#ifdef HAVE_LAPACK
            LEC,          /* linear equations */
            LIC,          /* linear inequalities */
            BLEC,         /* box and linear equations */
            BLIC,         /* box and linear inequalities */
            LEIC,         /* linear equations and linear inequalities */
            BLEIC,        /* box, linear equations and linear inequalities */
#endif // HAVE_LAPACK
        };
        /** constrain */
        static const std::string CONSTRAIN_STR[];

        /** differential method */
        enum DiffMethod {
            FORWARD,
            CENTRAL,
        };
        static const std::string DIFF_METHOD_STR[];

        static const Constrain  DEFAULT_CONSTRAIN;          //=Levmar::BOX;
        static const Bool       DEFAULT_USE_NUMERICAL_DIFF; //=false;
        static const DiffMethod DEFAULT_DIFF_METHOD;    //Levmar::FORWARD
        static const Bool       DEFAULT_USE_DATA_WEIGHTS;   //=true;

        static const UInt4      DEFAULT_MAX_ITERATIONS;    //=1000U;
        static const UInt4      DEFAULT_OUTPUT_INTERVAL;    // =10U;

        static const UInt4      DEFAULT_HISTORY_CAPACITY;   //=50;

        static const Double     DEFAULT_SCALING_FACTOR;     // =LM_INIT_MU;

        /** \deprecated */
        static const Double     DEFAULT_GRADIENT_TOLERANCE; // =LM_STOP_THRESH;
        /** \deprecated */
        static const Double     DEFAULT_TOLERANCE;          // =LM_STOP_THRESH
        /** \deprecated */
        static const Double     DEFAULT_RELATIVE_TOLERANCE; // =LM_STOP_THRESH

        static const Double     DEFAULT_RESIDU_ERR_THRESH;  //=LM_STOP_THRESH
        static const Double     DEFAULT_GRADIENT_THRESH;    //=LM_STOP_THRESH
        static const Double     DEFAULT_PARAM_DIFF_THRESH;  //=LM_STOP_THRESH

        static const Double     DEFAULT_DIFF_DELTA;     // =LM_DIFF_DELTA

        /** stopping stat of Levmar
         *
         *  the values that Levmar ver. 2.5 returns are 1 -- 7. 
         */
        enum LevmarStat {
            /* termination symbol ane their value that Levmar returns */
            SMALL_GRADIENT            = 1,
            SMALL_DP                  = 2,
            REACH_MAX_ITERATION       = 3,
            SINGULAR_MATRIX           = 4,
            NO_FURTHER_ERROR_REDUCTION= 5,
            SMALL_RESIDUAL_ERROR      = 6,
            INVALID_FUNC              = 7,
            /* additional symbol and their value for wrapper class*/
            CONTINUE                  = 8,
            FORCE_QUIT_BY_USER        = 9,
            SUSPEND                   =10,
        };
        /** termination reason, translate a LevmarStat value to a string */
        static const std::string TERMINATION_REASON[];
};

#endif // METHODTEST
