/**
 *
 * @file src/parser/PajeParser/PajeDefinition.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 Olivier Lagrasse
 * @author Augustin Degomme
 *
 * @date 2024-07-17
 */

#include <vector>
#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <stdexcept>
#include <map>
/* -- */
#include "parser/PajeParser/PajeDefinition.hpp"
/* -- */
using namespace std;

namespace PajeDef {

void print(std::vector<PajeFieldName> *fields, PajeDefinition *def) {
    unsigned int i;
    size_t size = def->_fields.size();

    cout << def->_trid << " : " << def->_name << endl;

    for (i = 0; i < size; i++) {
        PajeFieldName p;
        try {
            p = (*fields).at(def->_fields[i]._idname);
            cout << " " << p._name;
        } catch (out_of_range &e) {
            cout << " "
                 << "name not found";
        }
        string s;
        // as this won't change in the future, we can use a switch
        switch (def->_fields[i]._idtype) {
        case (1 << 0):
            s = "int";
            break;
        case (1 << 1):
            s = "hex";
            break;
        case (1 << 2):
            s = "date";
            break;
        case (1 << 3):
            s = "double";
            break;
        case (1 << 4):
            s = "string";
            break;
        case (1 << 5):
            s = "color";
            break;
        default:
            s = "error : wrong type";
            break;
        }
        cout << " " << s << endl;
    }
}

string print_string(std::vector<PajeFieldName> *fields, PajeDefinition *def) {
    unsigned int i;
    size_t size = def->_fields.size();
    // string       out;
    stringstream outstream;
    outstream << def->_name;
    outstream << "\n";
    for (i = 0; i < size; i++) {

        // try to find the name of the field we want to print

        PajeFieldName p;
        try {
            p = (*fields).at(def->_fields[i]._idname);
            outstream << " " << p._name;
        } catch (out_of_range &e) {
            outstream << " "
                      << "name not found";
        }
        string s;
        // as this won't change in the future, we can use a switch
        switch (def->_fields[i]._idtype) {
        case (1 << 0):
            s = "int";
            break;
        case (1 << 1):
            s = "hex";
            break;
        case (1 << 2):
            s = "date";
            break;
        case (1 << 3):
            s = "double";
            break;
        case (1 << 4):
            s = "string";
            break;
        case (1 << 5):
            s = "color";
            break;
        default:
            s = "error : wrong type";
            break;
        }
        outstream << " " << s;
        outstream << "\n";
    }

    return outstream.str();
}

bool check_definition(PajeDefinition *def) {
    int fdpresent = def->_fdpresent;

    // If the definition requires Alias or Name,
    // and the trace provide only one the both, it's ok
    if (((def->_fdrequired & CODE(_PajeFN_Alias)) || (def->_fdrequired & CODE(_PajeFN_Name))) && ((def->_fdpresent & CODE(_PajeFN_Alias)) || (def->_fdpresent & CODE(_PajeFN_Name)))) {
        fdpresent = fdpresent | CODE(_PajeFN_Alias);
        fdpresent = fdpresent | CODE(_PajeFN_Name);
    }

    if ((fdpresent & def->_fdrequired) == def->_fdrequired)
        return true;
    else
        return false;
}
}
