#include "Header.hh"

#include "ParamSet.hh"

Int4 main(Int4 aargc, Char *aargv[]) {

    ParamSet param;
    vector<Double> vc0, vc1;
    vector< vector<Double> > mx0, mx1;
    PeakData peakData;
    vector<FuncBase*> funcList;
    vector< vector<FuncBase*> > funcMatrix;

    vc0.push_back(1.0);
    vc0.push_back(2.0);
    vc0.push_back(3.0);

    mx0.push_back(*(new vector<Double>));
    mx0.push_back(*(new vector<Double>));
    std::cout << mx0.size() << endl;
    std::cout << mx0[0].size() << endl;
    mx1.push_back(*(new vector<Double>));
    mx1.push_back(*(new vector<Double>));
    mx1[0].push_back(0.0); 
    mx1[0].push_back(0.0); 
    mx1[1].push_back(0.0); 
    mx1[1].push_back(0.0); 
    std::cout << mx1.size() << endl;
    std::cout << mx1[0].size() << endl;

    peakData.add(PEAK, -3.5, 100000.0, 3.5, -7.0, 0.0);
    peakData.add(PEAK,  3.5, 100000.0, 3.5,  0.0, 7.0);


    /* for Bool */
    param.add("uniform knots", true);
    //param.add("uniform knots", true); // error shall occurs because of duplicated registration
    param.add("unformatted",  false);

    /* for Int4 */
    param.add("window width", 1);
    param.add("uppur bound",  1);
    param.add("order",        4);
    //param.add("order",        4); // error shall occuers because of duplicated registration

    /* for UInt4 */
    //param.add("order", 4U);
    //param.add("order", 4U); // error shall occuers because of duplicated registration

    /* for Double */
    param.add("pi", 3.1415926);
    //param.add("pi", 3.1415926); // error shall occuers because of duplicated registration
    param.add("base of natural logalithm", 2.7189);

    /* for vector */
    param.add("vc0", vc0);
    //param.add("vc0", vc0); // error shall occuers because of duplicated registration
    //param.add("vc1", vc1); // error shall occures since the size is zero.

    /* for matrix */
    //param.add("mx0", mx0); // error shall occures since the size is zero.
    param.add("mx1", mx1);
    //param.add("mx1", mx1); // error shall occures since the size is zero.

    /* for PeakData */
    param.add("peak data", peakData);

    std::cout << "dump test" << endl;
    param.dump();

    /* for Bool */
    std::cout << "uniform knots " << param.getBool("uniform knots") << endl;
    std::cout << "formatted     " << param.getBool("formatted") << endl;
    std::cout << "unformatted   " << param.getBool("unformatted") << endl;

    std::cout << "pi=   "  << param.getDouble("pi")      << endl;
    //std::cout << "gamma="  << param.getDouble("gamma")   << endl; // error shall occures since the key is not registed.
    std::cout << "order="  << param.getInt4("order")     << endl;
    //std::cout << "pi=   "  << param.getInt4("pi")        << endl; // error shall occures since the key is not registed.
    std::cout << "order="  << param.getUInt4("order")    << endl;
    //std::cout << "pi=   "  << param.getUInt4("pi")       << endl; // error shall occures since the key is not registed.

    /* for vector */
    std::cout << "vc0[0]=" << param.getDouble("vc0", 0U) << endl;
    //std::cout << "vc1[0]=" << param.getDouble("vc1", 0U) << endl; // error shall occures since the key is not registed.
    //std::cout << "vc0[5]=" << param.getDouble("vc0", 5U) << endl; // error shall occures since the index is out of range.

    /* for matrix */
    std::cout << "mx1[0][0]=" << param.getDouble("mx1", 0U, 0U) << endl;
    //std::cout << "mx1[5][0]=" << param.getDouble("mx1", 5U, 0U) << endl; // error shall occures since the index is out of range.
    //std::cout << "mx1[0][5]=" << param.getDouble("mx1", 0U, 5U) << endl; // error shall occures since the index is out of range.
    //std::cout << "mx0[0][0]=" << param.getDouble("mx0", 0U, 0U) << endl; // error shall occures since the key is not registed.

    /* for Bool */
    param.replace("uniform knots", false);
    //param.replace("formatted", false);
    //param.replace("unformatted", false);

    /* for Int4 */
    param.replace("window width", 11);
    std::cout << "order="  << param.getInt4("window width") << endl;

    /* for UInt4 */
    param.replace("order", 10U);
    std::cout << "order="  << param.getUInt4("order") << endl;

    /* for Double */
    param.replace("pi", 3.0);
    std::cout << "pi=   "  << param.getDouble("pi") << endl;

    /* for vector */
    param.replace("vc0", 2U, 4.0);
    std::cout << "vc0[2]=" << param.getDouble("vc0", 2U) << endl;
    vc1.push_back(1.0);
    vc1.push_back(1.0);
    vc1.push_back(1.0);
    vc1.push_back(2.0);
    vc1.push_back(2.0);
    vc1.push_back(2.0);
    param.replace("vc0", vc1);
    
    std::cout << "vc0=" << "(";
    for (std::vector<Double>::iterator i=vc0.begin(); i != vc0.end(); ++i) {
        std::cout << " " << *i;
    }
    std::cout << ")" << endl;
    std::cout << "vc1=" << "(";
    for (std::vector<Double>::iterator i=vc1.begin(); i != vc1.end(); ++i) {
        std::cout << " " << *i;
    }
    std::cout << ")" << endl;
    

    /* for matrix */
    param.replace("mx1", 0U, 0U, 4.0);
    std::cout << "mx1[0][0]=" << param.getDouble("mx1", 0U, 0U) << endl;
    mx0.push_back(*(new vector<Double>));
    mx0[0].push_back(1.0);
    mx0[0].push_back(1.0);
    mx0[0].push_back(1.0);
    mx0[1].push_back(2.0);
    mx0[1].push_back(2.0);
    mx0[1].push_back(2.0);
    mx0[2].push_back(3.0);
    mx0[2].push_back(3.0);
    mx0[2].push_back(3.0);
    param.replace("mx1", mx0);

    param.dump();

    vector<string> keyList=param.getKeyList();
    std::cout << "a list of keys" << endl;
    for (std::vector<string>::iterator i=keyList.begin(); i != keyList.end(); ++i) {
        std::cout << " " << "\"" << *i << "\"";
    }
    std::cout << endl;
    
}
