/**
 *
 * @file src/parser/PajeParser/ParserPaje.cpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 * @author Johnny Jazeix
 * @author Mathieu Faverge
 * @author Francois Trahay
 * @author Olivier Lagrasse
 *
 * @date 2024-07-17
 */
#include <iostream>
#include <fstream>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <list>
/* -- */
#include "common/Errors.hpp"
/* -- */
#include "trace/values/Values.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "parser/Parser.hpp"
/* -- */
#include "parser/PajeParser/PajeFileManager.hpp"
#include "parser/PajeParser/PajeDefinition.hpp"
#include "parser/PajeParser/ParserDefinitionPaje.hpp"
#include "parser/PajeParser/ParserEventPaje.hpp"
#include "parser/PajeParser/ParserPaje.hpp"
/* -- */
using namespace std;

ParserPaje::ParserPaje() :
    _ParserDefinition(new ParserDefinitionPaje()),
    _ParserEvent(new ParserEventPaje(_ParserDefinition)) { }

ParserPaje::ParserPaje(const string &filename) :
    Parser(filename),
    _ParserDefinition(new ParserDefinitionPaje()),
    _ParserEvent(new ParserEventPaje(_ParserDefinition)), _file(nullptr) { }

ParserPaje::~ParserPaje() {
    delete _ParserDefinition;
    delete _ParserEvent;
    if (_file != nullptr)
        delete _file;
}

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

    string filename = get_next_file_to_parse();

    static const string PERCENT = "%";

    while (filename != "") {
        // Open the trace
        try {
            _file = new PajeFileManager(filename.c_str());
        } catch (const char *) {
            delete _file;
            _file = nullptr;
            _is_canceled = true;
            finish();
            trace.finish();
            std::cerr << "Cannot open file " << filename.c_str() << std::endl;
            Error::set(Error::VITE_ERR_OPEN, 0, Error::VITE_ERRCODE_WARNING);
            return;
        }

        PajeLine_t line;
#ifdef DBG_PARSER_PAJE
        int lineid = 0;
#endif
        while ((!(_file->eof())) && !(_is_canceled)) {

            try {
#ifdef DBG_PARSER_PAJE
                if ((lineid + 1) == _file->get_line(&line)) {
                    _file->print_line();
                    lineid++;
                }
#else
                _file->get_line(&line);
#endif
            } catch (char *) {
                Error::set(Error::VITE_ERR_EXPECT_ID_DEF, 0, Error::VITE_ERRCODE_ERROR);
                continue;
            }

            // If it's an empty line
            if (line._nbtks == 0) {
                continue;
            }
            // The line starts by a '%' : it's a definition
            else if (line._tokens[0][0] == '%') {
                _ParserDefinition->store_definition(&line);
            }
            // It's an event
            else {
                _ParserEvent->store_event(&line, trace);
            }
        }
        delete _file;
        _file = nullptr;
        filename = get_next_file_to_parse();
    }

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

float ParserPaje::get_percent_loaded() const {
    if (_file != nullptr)
        return _file->get_percent_loaded();
    else
        return 0.;
}

ParserDefinitionPaje *ParserPaje::get_parser_def() const {
    return _ParserDefinition;
}
