/*
 ** This file is part of the ViTE project.
 **
 ** This software is governed by the CeCILL-A license under French law
 ** and abiding by the rules of distribution of free software. You can
 ** use, modify and/or redistribute the software under the terms of the
 ** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
 ** URL: "http://www.cecill.info".
 **
 ** As a counterpart to the access to the source code and rights to copy,
 ** modify and redistribute granted by the license, users are provided
 ** only with a limited warranty and the software's author, the holder of
 ** the economic rights, and the successive licensors have only limited
 ** liability.
 **
 ** In this respect, the user's attention is drawn to the risks associated
 ** with loading, using, modifying and/or developing or reproducing the
 ** software by the user in light of its specific status of free software,
 ** that may mean that it is complicated to manipulate, and that also
 ** therefore means that it is reserved for developers and experienced
 ** professionals having in-depth computer knowledge. Users are therefore
 ** encouraged to load and test the software's suitability as regards
 ** their requirements in conditions enabling the security of their
 ** systems and/or data to be ensured and, more generally, to use and
 ** operate it in the same conditions as regards security.
 **
 ** The fact that you are presently reading this means that you have had
 ** knowledge of the CeCILL-A license and that you accept its terms.
 **
 **
 ** ViTE developers are (for version 0.* to 1.0):
 **
 **        - COULOMB Kevin
 **        - FAVERGE Mathieu
 **        - JAZEIX Johnny
 **        - LAGRASSE Olivier
 **        - MARCOUEILLE Jule
 **        - NOISETTE Pascal
 **        - REDONDY Arthur
 **        - VUCHENER Clément
 **
 */

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <list>
#include <stack>
/* -- */
#include <QDir>
#include <QFileInfo>
/* -- */
#include "common/Errors.hpp"
/* -- */
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "parser/Parser.hpp"
#include "parser/PajeParser/ParserVite.hpp"
#include "parser/PajeParser/PajeFileManager.hpp"
#include "parser/PajeParser/ParserPaje.hpp"
#include "parser/PajeParser/ParserEventPaje.hpp"
#include "parser/PajeParser/ParserDefinitionPaje.hpp"
/* -- */
using namespace std;

ParserVite::ParserVite() {}
ParserVite::ParserVite(const std::string &filename) : Parser(filename) {}
ParserVite::~ParserVite() {}

void ParserVite::parse(Trace &trace,
                       bool   finish_trace_after_parse){

    ParserPaje       parserpaje(_file_to_parse);

    QString                          name;
    stack<Container *>               CTstack;
    const Container::Vector         *root_containers;
    const map<std::string, Value *> *extra_fields;
    map<string, Value *>::const_iterator fnamefield;

    // Store the absolute directory of the first file for relative path in the others
    QString          absdir = QFileInfo(_file_to_parse.c_str()).absolutePath();

    // Parse the first file with definitions
    try {
        parserpaje.parse(trace, false);
    }
    catch(...) {
        finish();
        trace.finish();
        return ;
    }

#ifdef DBG_PARSER_VITE
    std::cerr << "First file parsed" << std::endl;
    std::cerr << "Add container : ";
#endif

    /* Loop over root containers to add them in the stack */
    root_containers = trace.get_root_containers();

    for (Container::VectorIt it = root_containers->begin();
         it != root_containers->end(); it++) {
#ifdef DBG_PARSER_VITE
        std::cerr << "+";
#endif
        CTstack.push(*it);
    }

#ifdef DBG_PARSER_VITE
    std::cerr << std::endl;
#endif

    /* Deep-First search over container to parse extra files */
    while ( ! CTstack.empty()) {
        Container *c = CTstack.top();
        CTstack.pop();

        extra_fields = c->get_extra_fields();
        fnamefield = extra_fields->find(string("FileName"));

        // Search the filename
        if (fnamefield != extra_fields->end()) {
            name = QString::fromStdString( ((String *)(*fnamefield).second)->to_string() );
        }
        else {
            name = "";
        }

        if(name != "") {
#ifdef DBG_PARSER_VITE
            std::cerr << ( (absdir + QDir::separator() + name).toStdString() ) << std::endl;
#endif
            parserpaje.set_file_to_parse( (absdir + QDir::separator() + name).toStdString() );

            try {
                parserpaje.parse(trace, false);
            }
            catch(...) {
                finish();
                trace.finish();
                return ;
            }
        }

        // We add the children
        Container::VectorIt children_end = c->get_children()->end();
        for (Container::VectorIt i = c->get_children()->begin();
             i != children_end; ++ i) {
            CTstack.push(*i);
        }
    }

    finish();

    if(finish_trace_after_parse) {
        trace.finish();
    }
}

float ParserVite::get_percent_loaded() const{
    // TODO when multithread :) else we cannot determine it except in computing the sum of all the file sizes and storing already loaded ^^
    return 0.5;
}
