#include "../test.h"
#include "arc/std/lexer.h"

ARC_TEST(Lexer_Char_Match){
    ARC_Lexer *lexer;
    ARC_Lexer_Create(&lexer);

    ARC_Lexer_InitBasicTokenRules(lexer);

    ARC_String *simple;
    ARC_String_CreateWithStrlen(&simple, "::{}!/.");

    ARC_Lexer_LexString(lexer, &simple);

    ARC_LexerToken *token;

    token = ARC_Lexer_GetToken(lexer, 0);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_COLON_ID);

    token = ARC_Lexer_GetToken(lexer, 1);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_COLON_ID);

    token = ARC_Lexer_GetToken(lexer, 2);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_LEFT_CURLY_BRACE_ID);

    token = ARC_Lexer_GetToken(lexer, 3);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_RIGHT_CURLY_BRACE_ID);

    token = ARC_Lexer_GetToken(lexer, 4);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_BANG_ID);

    token = ARC_Lexer_GetToken(lexer, 5);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_FORWARD_SLASH_ID);

    token = ARC_Lexer_GetToken(lexer, 6);
    ARC_CHECK(token->rule == ARC_LEXER_TOKEN_PERIOD_ID);

    ARC_Lexer_Destroy(lexer);
}

ARC_TEST(Lexer_Check_Id_Basic){
    ARC_Lexer *lexer;
    ARC_Lexer_Create(&lexer);

    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(0,  0 ));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(1, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(2, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(3, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(4, ':'));

    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 0) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 7) == ARC_False);
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 2) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 4) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 5) == ARC_False);

    ARC_Lexer_Destroy(lexer);
}

ARC_TEST(Lexer_Check_Id_Unordered_But_Continious){
    ARC_Lexer *lexer;
    ARC_Lexer_Create(&lexer);

    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(2, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(0,  0 ));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(3, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(1, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(4, ':'));

    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 0) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 7) == ARC_False);
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 2) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 4) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 5) == ARC_False);

    ARC_Lexer_Destroy(lexer);
}

ARC_TEST(Lexer_Check_Id_Unordered_Not_Continious){
    ARC_Lexer *lexer;
    ARC_Lexer_Create(&lexer);

    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(2, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(8,  0 ));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(3, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(1, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(4, ':'));

    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 8) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 7) == ARC_False);
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 2) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 4) == ARC_True );
    ARC_CHECK(ARC_Lexer_IsTokenId(lexer, 5) == ARC_False);

    ARC_Lexer_Destroy(lexer);
}

ARC_TEST(Lexer_Check_Continious){
    ARC_Lexer *lexer;
    ARC_Lexer_Create(&lexer);

    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(2, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(0,  0 ));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(3, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(1, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(4, ':'));

    ARC_CHECK(ARC_Lexer_IsContinious(lexer) == ARC_True);

    ARC_Lexer_Destroy(lexer);
}

ARC_TEST(Lexer_Check_Not_Continious){
    ARC_Lexer *lexer;
    ARC_Lexer_Create(&lexer);

    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(2, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(8,  0 ));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(3, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(1, ':'));
    ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(4, ':'));

    ARC_CHECK(ARC_Lexer_IsContinious(lexer) == ARC_False);

    ARC_Lexer_Destroy(lexer);
}
