#include "memory.h"
#include "print.h"
#include "strings.h"
#include "stdint.h"
#include "stddef.h"
#include "basic.h"



// Utility: Find or create a variable by name
Variable* get_variable(InterpreterState* state, const char* name) {
    for (size_t i = 0; i < state->variable_count; i++) {
        if (strcmp(state->variables[i].name, name) == 0) {
            return &state->variables[i];
        }
    }
    if (state->variable_count < MAX_VARIABLES) {
        Variable* var = &state->variables[state->variable_count++];
        strncpy(var->name, name, sizeof(var->name) - 1);
        var->name[sizeof(var->name) - 1] = '\0';
        var->value = 0;
        var->str_value = NULL;
        return var;
    }
    return NULL; // No space for more variables
}

// Parse an integer from a string, skipping leading whitespace
int parse_int(const char* str) {
    while (*str == ' ') str++; // Skip leading spaces
    int result = 0;
    int sign = 1;
    if (*str == '-') {
        sign = -1;
        str++;
    }
    while (*str >= '0' && *str <= '9') {
        result = result * 10 + (*str - '0');
        str++;
    }
    return result * sign;
}




const char* evaluate_expression(InterpreterState* state, const char* expr) {
    char buffer[64];
    strncpy(buffer, expr, sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0';

    char* plus = strrchr(buffer, '+');
    if (plus) {
        *plus = '\0';

        // Evaluate the left and right sides only once
        const char* left = evaluate_expression(state, buffer);
        const char* right = evaluate_expression(state, plus + 1);

        // Debug output
        printf("DEBUG: Left operand: %s\n", left);
        printf("DEBUG: Right operand: %s\n", right);

        // Check if both sides are numeric
        int left_is_number = (left[0] >= '0' && left[0] <= '9') || (left[0] == '-' && left[1] >= '0' && left[1] <= '9');
        int right_is_number = (right[0] >= '0' && right[0] <= '9') || (right[0] == '-' && right[1] >= '0' && right[1] <= '9');

        static char result[128];

        if (left_is_number && right_is_number) {
            // Parse the left and right operands
            int left_value = parse_int(left);
            int right_value = parse_int(right);

            // Correct addition logic
            int sum = left_value + right_value;

            // Debug addition
            printf("DEBUG: Adding %d + %d = %d\n", left_value, right_value, sum);

            // Format the result as a string
            snprintf(result, sizeof(result), "%d", sum);
        } else {
            // Concatenate strings
            snprintf(result, sizeof(result), "%s%s", left, right);

            // Debug string concatenation
            printf("DEBUG: Concatenating strings: %s + %s = %s\n", left, right, result);
        }
        return result;
    }

    // Trim leading and trailing spaces
    const char* start = buffer;
    while (*start == ' ') start++;

    char* end = buffer + strlen(buffer) - 1;
    while (end > start && *end == ' ') *end-- = '\0';

    if (start[0] >= 'A' && start[0] <= 'Z') {
        Variable* var = get_variable(state, start);
        if (var) {
            static char var_result[64];
            if (var->str_value) {
                strncpy(var_result, var->str_value, sizeof(var_result) - 1);
                var_result[sizeof(var_result) - 1] = '\0';
                return var_result;
            } else {
                snprintf(var_result, sizeof(var_result), "%d", var->value);
                return var_result;
            }
        }
    }

    if (start[0] == '"') {
        // String literal
        size_t len = strlen(start);
        if (start[len - 1] == '"') {
            static char str_result[64];
            strncpy(str_result, start + 1, len - 2);
            str_result[len - 2] = '\0';
            return str_result;
        }
    }

    static char int_result[16];
    snprintf(int_result, sizeof(int_result), "%d", parse_int(start));
    return int_result;
}



// Interpret a single line of code
void interpret_line(InterpreterState* state, const char* line) {
    if (strncmp(line, "LET", 3) == 0) {
        const char* rest = line + 3;
        while (*rest == ' ') rest++;
        const char* equals = strchr(rest, '=');
        if (!equals) return;

        char var_name[16];
        strncpy(var_name, rest, equals - rest);
        var_name[equals - rest] = '\0';

        // Trim trailing spaces from var_name
        size_t len = strlen(var_name);
        while (len > 0 && var_name[len - 1] == ' ') {
            var_name[--len] = '\0';
        }

        Variable* var = get_variable(state, var_name);
        if (var) {
            const char* value = evaluate_expression(state, equals + 1);
            if (value[0] >= '0' && value[0] <= '9') {
                var->value = parse_int(value);
                var->str_value = NULL;
            } else {
                var->str_value = malloc(strlen(value) + 1);
                strcpy(var->str_value, value);
            }
        }
    } else if (strncmp(line, "PRINT", 5) == 0) {
        const char* rest = line + 5;
        while (*rest == ' ') rest++;
        const char* value = evaluate_expression(state, rest);
        printf("%s\n", value);
    } else if (strncmp(line, "END", 3) == 0) {
        printf("Program terminated.\n");
        state->running = 0;
    }
}

// Initialize interpreter state
void init_state(InterpreterState* state) {
    state->variable_count = 0;
    state->running = 1;
}

// Execute a single line in the context of a state
void execute_line(InterpreterState* state, const char* line) {
    printf("Executing line: %s\n", line); // Debugging
    interpret_line(state, line);
}

