/**
 *
 * @file src/common/Errors.hpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 * @author Johnny Jazeix
 * @author Arthur Redondy
 * @author Mathieu Faverge
 *
 * @date 2024-07-17
 */
#ifndef ERRORS_HPP
#define ERRORS_HPP

/*!
 * \file Errors.hpp
 * This file contains all the significations of the errors or warnings that can be thrown by the parser
 *
 **/
/*! \class Error
 *  \brief Define errors and warnings used in the parser.
 */
class Error
{
private:
    Error();
    static int _line_error;

    static std::queue<std::string> _errors;
    static std::queue<std::string> _warnings;
    static std::string _content;

public:
    /*
     * Priorities of errors
     */
    /*!
     * \brief Define the priority _ERROR.
     */
    const static int VITE_ERRCODE_EVERYTHING;

    /*!
     * \brief Define the priority _WARNING.
     */
    const static int VITE_ERRCODE_WARNING;

    /*!
     * \brief Define the priority _ERROR.
     */
    const static int VITE_ERRCODE_ERROR;

    /*
     * Kind of errors known
     */
    /*!
     * \brief Define the error when expected the character " (before the end of the file).
     */
    const static std::string VITE_ERR_PARSE;
    /*!
     * \brief Define the error when the mmap function fails.
     */
    const static std::string VITE_ERR_MMAP;
    /*!
     * \brief Define the error when the file is empty.
     */
    const static std::string VITE_ERR_EMPTY_FILE;
    /*!
     * \brief Define the error when the fstat function fails.
     */
    const static std::string VITE_ERR_FSTAT;
    /*!
     * \brief Define the error when the open function fails.
     */
    const static std::string VITE_ERR_OPEN;
    /*!
     * \brief Define the error when the munmap function fails.
     */
    const static std::string VITE_ERR_MUNMAP;
    /*!
     * \brief Define the error when missing the end of a definition.
     */
    const static std::string VITE_ERR_EXPECT_END_DEF;
    /*!
     * \brief Define the error when missing the beginning of a definition.
     */
    const static std::string VITE_ERR_EXPECT_EVENT_DEF;
    /*!
     * \brief Define the error when missing the name of a definition.
     */
    const static std::string VITE_ERR_EXPECT_NAME_DEF;
    /*!
     * \brief Define the error when missing the identity of a definition.
     */
    const static std::string VITE_ERR_EXPECT_ID_DEF;
    /*!
     * \brief Define the error when the identity of a definition doesn't match with any definition defined.
     */
    const static std::string VITE_ERR_UNKNOWN_ID_DEF;
    /*!
     * \brief Define the error when some extra tokens are ignored at the end of a line.
     */
    const static std::string VITE_ERR_EXTRA_TOKEN;
    /*!
     * \brief Define the error when an event doesn't match with the event with the same name know by the parser.
     */
    const static std::string VITE_ERR_UNKNOWN_EVENT_DEF;
    /*!
     * \brief Define the error when missing the type of a field in a definition.
     */
    const static std::string VITE_ERR_FIELD_TYPE_MISSING;
    /*!
     * \brief Define the error when the type of a field in not recognized by the parser.
     */
    const static std::string VITE_ERR_FIELD_TYPE_UNKNOWN;
    /*!
     * \brief Define the error when a definition has no field.
     */
    const static std::string VITE_ERR_EMPTY_DEF;
    /*!
     * \brief Define the error when a value don't match with its type.
     */
    const static std::string VITE_ERR_INCOMPATIBLE_VALUE_IN_EVENT;
    /*!
     * \brief Define the error when the file which has to be parse doesn't have the right extension.
     */
    const static std::string VITE_ERR_BAD_FILE_EXTENSION;
    /*!
     * \brief Define the error when some field values are missing for an event.
     */
    const static std::string VITE_ERR_LINE_TOO_SHORT_EVENT;

    //////
    /// Errors from undefined entities
    //////

    /*!
     * \brief Define the error when a container type does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_CONTAINER_TYPE;
    /*!
     * \brief Define the error when a containere does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_CONTAINER;
    /*!
     * \brief Define the error when an event type does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_EVENT_TYPE;
    /*!
     * \brief Define the error when a state type does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_STATE_TYPE;
    /*!
     * \brief Define the error when a variable type does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_VARIABLE_TYPE;
    /*!
     * \brief Define the error when a link type does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_LINK_TYPE;
    /*!
     * \brief Define the error when a entity type does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_ENTITY_TYPE;

    /*!
     * \brief Define the error when a entity value does not exist.
     */
    const static std::string VITE_ERR_UNKNOWN_ENTITY_VALUE;

    const static std::string VITE_ERR_EVENT_ALREADY_DEF;
    const static std::string VITE_ERR_FIELD_NAME_MISSING;
    const static std::string VITE_ERR_FIELD_NOT_ALLOWED;
    const static std::string VITE_ERR_EVENT_NOT_CORRECT;

    /*!
     *  \fn set(const std::string &kind_of_error, const int priority) static void
     *  \brief raise an error or a warning
     *  \param kind_of_error : content of error
     *  \param priority : _ERROR or _WARNING
     */
    static void set(const std::string &kind_of_error, const int priority);

    /*!
     *  \fn set(const std::string &kind_of_error, const unsigned int line_number, const int priority) static void
     *  \brief raise an error or a warning
     *  \param kind_of_error : content of error
     *  \param line_number : the line in the trace file where the error occurs.
     *  \param priority : _ERROR or _WARNING
     */
    static void set(const std::string &kind_of_error, const unsigned int line_number, const int priority);
    /*!
     *  \fn set_and_print(const std::string &kind_of_error, const int priority) static void
     *  \brief raise and throw to the interface an error or a warning
     *  \param kind_of_error : content of error
     *  \param priority : _ERROR or _WARNING
     */
    static void set_and_print(const std::string &kind_of_error, const int priority);

    /*!
     *  \fn set_and_print(const std::string &kind_of_error, const unsigned int line_number, const int priority) static void
     *  \brief raise and throw to the interface an error or a warning and the line when it occurs
     *  \param kind_of_error : content of error
     *  \param line_number : position of the error in the trace
     *  \param priority : _ERROR or _WARNING
     */
    static void set_and_print(const std::string &kind_of_error, const unsigned int line_number, const int priority);

    /*!
     *  \fn print(const int priority) static void
     *  \brief print the current error
     *  \param priority : _ERROR or _WARNING
     */
    static void print(const int priority);

    /*!
     *  \fn print(const std::string &content, const int priority) static void
     *  \brief print the current error
     *  \param content : the string we want to print
     *  \param priority : _ERROR or _WARNING
     */
    static void print(const std::string &content, const int priority);

    /*!
     *  \fn set_if(bool condition, const std::string &kind_of_error, const unsigned int line_number, const int priority) static bool
     *  \brief raise an error or a warning and the line when it occurs if the condition is satisfied
     *  \param condition : a condition
     *  \param kind_of_error : content of error
     *  \param line_number : position of the error in the trace
     *  \param priority : _ERROR or _WARNING
     *  \return true if the condition is satisfied
     */
    static bool set_if(bool condition, const std::string &kind_of_error, const unsigned int line_number, const int priority);

    /*!
     *  \fn print_numbers() static void
     *  \brief throw to the interface a message about the number of errors and warnings
     */
    static void print_numbers();

    /*!
     *  \fn flush(const std::string &filename) static void
     *  \brief print all the errors and warnings saved in a file and empty the queues _errors and _warnings
     *  \param log_file_name log file in which the output will be written
     *  \param trace_file_name The file that was opened when flush was called
     */
    static void flush(const std::string &log_file_name, const std::string &trace_file_name);
};

#endif // ERRORS_HPP
