/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#include <memory>   // std::auto_ptr
#include <iostream>
#include <fstream>
#include <map>

#include <MonitoringManager.h>
#include <MonitoringManagerFactory.h>

// pml component is needed
#include <pml/MultiComponent.h>

#ifdef MML_GENERATE_GUI
#include <QApplication>
#endif
#include <map>

using namespace std;

int
main(int argc, char* argv[]) {
    if (argc != 2) {
        cout << "usage: " << argv[0] << " file.txt" << endl;
        cout << "file.txt should a text file with:" << endl;
        cout << "file.mml" << endl;
        cout << "out" << endl;
        cout << "parameterToExplore valMin valMax step" << endl;
        cout << "parameter1 val1" << endl;
        cout << "parameter2 val2" << endl;
        cout << "parameter3 val3" << endl;
        cout << "etc..." << endl;

        exit(0);
    }

    try {
#ifdef MML_GENERATE_GUI
        QApplication app(argc, argv);
#endif

        std::string mmlFile;
        std::string parameterToExplore;
        std::string out;
        double valMin, valMax, step, current;
        std::map<std::string, std::string> parameters;
        ifstream file;
        ofstream outFile;
        std::string s1, s2;
        cout << "reading " << argv[1]   << endl;
        file.open(argv[1], ios::in);
        if (file.bad()) {
            cout << "reading " << argv[1] << " failed"  << endl;
            exit(1);
        }
        file >> mmlFile;
        cout << "mml file read" << endl;
        file >> out;
        cout << "output file read" << endl;
        file >> parameterToExplore;
        file >> valMin;
        current = valMin;
        file >> valMax;
        file >> step;
        cout << "Parameter to explore read" << endl;
        file >> s1;
        while (!file.eof()) {
            file >> s2;
            parameters.insert(std::pair<std::string, std::string>(s1, s2));
            file >> s1;
        }
        cout << "Parameters read" << endl;

        outFile.open(out.c_str(), ios::out);

        while (current < valMax) {
            cout << "Computation for " << parameterToExplore << " = " << current << endl;
            MonitoringManager* m = MonitoringManagerFactory::createManager(mmlFile.c_str());
            Properties* prop = m->getPml()->getExclusiveComponents()->getProperties();
            std::map<std::string, std::string>::iterator iter;
            for (iter = parameters.begin(); iter != parameters.end(); ++iter) {
                prop->set(iter->first, iter->second);
            }
            prop->set(parameterToExplore, current);

            if (m->init()) {
                m->doMove();
                while (!m->checkStop()) {
                    m->doMove();
                }
            }
            cout << "Computation finished, exporting results to output file" << endl;

            outFile << parameterToExplore << ": " << current << std::endl;
            for (int i = 0; i < m->numberOfMonitor(); i++) {
                outFile << "Monitor " << i << ": ";
                for (int j = 0; j < m->getMonitor(i)->getNumberOfValues(); j++) {
                    outFile << m->getMonitor(i)->getValue(j) << " ";
                }
                outFile << endl;
            }
            m->end();
            current += step;
            delete m;
        }

    }
    catch (const xml_schema::exception& e) {
        cerr << e << endl;
        return 1;
    }
}

