#include <string>
#include <vector>
using namespace std;

#include "include/test.h"

#include "../src/include/tokenize.h"

int main() {
    _TEST_PRESENTATION("Lexer");

    /* Complex input */
    {
        string input = "int a = x+++7;";

        vector<Token> tokens = tokenize({ input });

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens.size() == 8),
            "Il devrait y avoir 8 tokens",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[0].type == TokenType::Type),
            "Le premier token devrait être de type 'Type'",
            false
        )
        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(get<Type>(tokens[0].data) == Type::Int),
            "Les données du premier token devraient être 'Int'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[1].type == TokenType::Identifier),
            "Le deuxième token devrait être un 'Identifiant'",
            false
        )
        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(get<string>(tokens[1].data) == "a"),
            "Les données du deuxième token devraient être 'a'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[2].type == TokenType::Equal),
            "Le troisième token devrait être 'Equal'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[3].type == TokenType::Identifier),
            "Le quatrième token devrait être un 'Identifiant'",
            false
        )
        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(get<string>(tokens[3].data) == "x"),
            "Les données du quatrième token devraient être 'x'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[4].type == TokenType::DoublePlus),
            "Le cinquième token devrait être 'DoublePlus'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[5].type == TokenType::Plus),
            "Le cinquième token devrait être 'Plus'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[6].type == TokenType::Int),
            "Le premier token devrait être de type 'Int'",
            false
        )
        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(get<int>(tokens[6].data) == 7),
            "Les données du premier token devraient être '7'",
            false
        )

        _TEST_ASSERT(
            _TEST_NO_EXCEPTION(tokens[7].type == TokenType::Semicolon),
            "Le cinquième token devrait être 'Semicolon'",
            false
        )

        _TEST_ASSERT(true, "+++", true)
    }

    /* Incorrect input */
    {
        string input = "int a = 10 @;";

        _TEST_ASSERT(
            _TEST_IS_EXCEPTION(tokenize({ input }), TokenError),
            "Token invalide",
            true
        )
    }

    return 0;
}