// Kyler Olsen
// YREA SLS
// Tests Header
// October 2025

#ifndef SLS_LEXER_TEST_HELPERS_H
#define SLS_LEXER_TEST_HELPERS_H

#include <stddef.h>

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

#include "sls/errors.h"
#include "sls/bool.h"
#include "sls/lexer.h"
#include "sls/string.h"
#include "tests/lexer_test_helpers.h"
#include "tests/tests.h"

typedef struct {
    TestResult result;
    LexerInfo lexer_info;
} LexerTest;

typedef struct {
    Boolean is_literal;
    SlsStr name;
} TestIdentifierValue;

typedef struct {
    IntegerBuiltInType type;
    uint64_t value;
} TestIntegerValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    TestIdentifierValue *values;
} TestArrayIdentifierValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    TestIntegerValue *values;
} TestArrayIntegerValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    float *values;
} TestArrayFloatValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    double *values;
} TestArrayDoubleValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    SlsStr *values;
} TestArrayStringValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    Boolean *values;
} TestArrayBooleanValue;

typedef struct {
    size_t dimensions;
    size_t *shape;
    SlsStr struct_name;
    Boolean (*struct_handler)(LexerTest *, LexerResult, size_t, size_t, void *, void *);
    void **values;
} TestArrayStructInlineValue;

typedef struct {
    Boolean (*token_handler)(LexerTest *, LexerResult, size_t, void *);
    void *value;
} TestTokenStringToken;

typedef struct {
    size_t tokens;
    TestTokenStringToken *values;
} TestTokenStringValue;

typedef struct {
    size_t input_length;
    TestIdentifierValue *input_values;
    size_t output_length;
    TestIdentifierValue *output_values;
} TestTypeTupleValue;

LexerTest start_up_test(SlsStr test_name, SlsStr test_code);
void clean_up_test(LexerResult result);
TestResult error_test_out_of_mem(LexerTest *test);
TestResult error_test(LexerTest *test, LexerResult result, SlsError error);
TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message);
TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error);
TestResult skip_test(LexerTest *test, LexerResult result);
TestResult skip_test_no_result(LexerTest *test);
TestResult pass_test(LexerTest *test, LexerResult result);

Boolean test_eof_value(LexerTest *test, LexerResult result, size_t i, void *_);
Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, TestIdentifierValue *value);
Boolean test_integer_value(LexerTest *test, LexerResult result, size_t i, TestIntegerValue *value);
Boolean test_character_value(LexerTest *test, LexerResult result, size_t i, uint8_t *value);
Boolean test_float_value(LexerTest *test, LexerResult result, size_t i, float *value);
Boolean test_double_value(LexerTest *test, LexerResult result, size_t i, double *value);
Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr *value);
Boolean test_boolean_value(LexerTest *test, LexerResult result, size_t i, Boolean *value);
Boolean test_array_identifier_value(LexerTest *test, LexerResult result, size_t i, TestArrayIdentifierValue *values);
Boolean test_array_integer_value(LexerTest *test, LexerResult result, size_t i, TestArrayIntegerValue *values);
Boolean test_array_float_value(LexerTest *test, LexerResult result, size_t i, TestArrayFloatValue *values);
Boolean test_array_double_value(LexerTest *test, LexerResult result, size_t i, TestArrayDoubleValue *values);
Boolean test_array_string_value(LexerTest *test, LexerResult result, size_t i, TestArrayStringValue *values);
Boolean test_array_boolean_value(LexerTest *test, LexerResult result, size_t i, TestArrayBooleanValue *values);
Boolean test_array_struct_inline_value(LexerTest *test, LexerResult result, size_t i, TestArrayStructInlineValue *values);
Boolean test_token_string_value(LexerTest *test, LexerResult result, size_t i, TestTokenStringValue *values);
Boolean test_type_tuple_value(LexerTest *test, LexerResult result, size_t i, TestTypeTupleValue *values);
Boolean test_for_error(LexerTest *test, LexerResult result, size_t i, SlsStr *error);

#endif // SLS_LEXER_TEST_HELPERS_H
