/*
** 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
**
*/
/**
 *  @file ParserOTF.cpp
 *
 *  @author Lagrasse Olivier
 *  @author Johnny Jazeix
 *  @author Mathieu Faverge
 *
 */

#include <iostream>
#include <fstream>
#include <string>
#include <map>
/* -- */
#include <otf.h>
/* -- */
#include <QObject>
/* -- */
#include "trace/values/Values.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "parser/Parser.hpp"
#include "parser/OTFParser/ParserOTF.hpp"
#include "parser/OTFParser/ParserDefinitionOTF.hpp"
#include "parser/OTFParser/ParserEventOTF.hpp"
/* -- */

using namespace std;

#define VITE_OTF_MAXFILES_OPEN 100

#define VITE_ERR_OTF_FILEMANAGER "Failed to open OTF File Manager\n"
#define VITE_ERR_OTF_OPENREADER  "Failed to create the OTF Reader\n"


ParserOTF::ParserOTF() {};
ParserOTF::ParserOTF(const string &filename) : Parser(filename) {}
ParserOTF::~ParserOTF() {};

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

    ParserDefinitionOTF *parserdefinition;
    ParserEventOTF      *parserevent;
    OTF_FileManager     *manager;
    OTF_Reader          *reader;
    int ret = 0;
    const std::string filename = get_next_file_to_parse();
    if(filename == "")
        return;

    manager = OTF_FileManager_open(VITE_OTF_MAXFILES_OPEN);
    if(manager == NULL) {
        cerr << QObject::tr(VITE_ERR_OTF_FILEMANAGER).toStdString() << endl;
        return;
    }

    reader = OTF_Reader_open(filename.c_str(), manager);
    if(reader == NULL) {
        cerr << QObject::tr(VITE_ERR_OTF_OPENREADER).toStdString() << endl;
        OTF_FileManager_close(manager);
        finish();

        if(finish_trace_after_parse) { // true by default
            trace.finish();
        }
        return;
    }

    parserdefinition = new ParserDefinitionOTF();
    parserdefinition->set_handlers(&trace);
    parserdefinition->read_definitions(reader);
    parserdefinition->create_container_types(&trace);

    //parserdefinition->print_definitions();

    parserevent = new ParserEventOTF();
    parserevent->set_number_event_read_by_each_pass(reader, 10000);
    parserevent->set_handlers(&trace);

    while ( ((ret = parserevent->read_events(reader)) != 0)
            && (!_is_canceled)) {
        if(ret == -1) {
            cerr << QObject::tr("Error while reading events. Aborting").toStdString() << endl;
            break;
        }
    }

    parserevent->read_markers(reader);

    finish();

    if(finish_trace_after_parse) { // true by default
        trace.finish();
    }

    delete parserevent;
    delete parserdefinition;

    OTF_Reader_close(reader);
    OTF_FileManager_close(manager);
}


float ParserOTF::get_percent_loaded() const {
    return ParserEventOTF::get_percent_loaded();
}
