CC = gcc
CFLAGS = -Wall -Wextra -O2 -Isrc
LDFLAGS = -lm -lpthread

SRC_DIR = src
TEST_DIR = tests
EXAMPLE_DIR = examples
BUILD_DIR = build
BIN_DIR = bin

TARGET = $(BIN_DIR)/rc

SOURCES = $(SRC_DIR)/main.c \
          $(SRC_DIR)/globals.c \
          $(SRC_DIR)/tokenizer.c \
          $(SRC_DIR)/parser.c \
          $(SRC_DIR)/interpreter.c \
          $(SRC_DIR)/native_functions.c \
          $(SRC_DIR)/string_utils.c \
          $(SRC_DIR)/preprocessor.c \
          $(SRC_DIR)/oop.c \
          $(SRC_DIR)/stdlib/stdlib.c \
          $(SRC_DIR)/stdlib/string/string_stdlib.c \
          $(SRC_DIR)/stdlib/math/math_stdlib.c \
          $(SRC_DIR)/stdlib/io/file_stdlib.c \
          $(SRC_DIR)/stdlib/io/socket_stdlib.c \
          $(SRC_DIR)/stdlib/async/async_stdlib.c \
          $(SRC_DIR)/stdlib/constants/constants_stdlib.c

OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)

TESTS = $(TEST_DIR)/feature_test.rc \
        $(TEST_DIR)/endless_loop_test.rc \
        $(TEST_DIR)/math_test.rc \
        $(TEST_DIR)/string_test.rc \
        $(TEST_DIR)/string_manip_test.rc \
        $(TEST_DIR)/increment_decrement_test.rc \
        $(TEST_DIR)/file_io_test.rc \
        $(TEST_DIR)/double_test.rc \
        $(TEST_DIR)/break_continue_test.rc \
        $(TEST_DIR)/async_io_test.rc \
        $(TEST_DIR)/array_test.rc \
        $(TEST_DIR)/pointer_test.rc \
        $(TEST_DIR)/logical_test.rc \
        $(TEST_DIR)/comparison_test.rc \
        $(TEST_DIR)/functions_test.rc \
        $(TEST_DIR)/trig_test.rc \
        $(TEST_DIR)/file_seek_test.rc \
        $(TEST_DIR)/include_test.rc \
        $(TEST_DIR)/nested_include_test.rc \
        $(TEST_DIR)/async_await_test.rc \
        $(TEST_DIR)/oop_step0.rc \
        $(TEST_DIR)/oop_step1.rc \
        $(TEST_DIR)/oop_fields.rc \
        $(TEST_DIR)/oop_method.rc \
        $(TEST_DIR)/oop_working.rc \
        $(TEST_DIR)/oop_mutation_test.rc \
        $(TEST_DIR)/oop_advanced.rc

EXAMPLES = $(EXAMPLE_DIR)/http_simple.rc \
           $(EXAMPLE_DIR)/http_persistent.rc \
           $(EXAMPLE_DIR)/http_multi.rc \
           $(EXAMPLE_DIR)/async_demo.rc

.PHONY: all clean test run-tests run-examples help

all: dirs $(TARGET)

dirs:
	@mkdir -p $(BUILD_DIR) $(BIN_DIR)
	@mkdir -p $(BUILD_DIR)/stdlib/string
	@mkdir -p $(BUILD_DIR)/stdlib/math
	@mkdir -p $(BUILD_DIR)/stdlib/io
	@mkdir -p $(BUILD_DIR)/stdlib/async
	@mkdir -p $(BUILD_DIR)/stdlib/constants

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@

$(TARGET): dirs $(OBJECTS)
	$(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS)

clean:
	rm -rf $(BUILD_DIR) $(BIN_DIR)

test: $(TARGET)
	@echo "=== Running All Tests ==="
	@echo ""
	@echo "Running feature tests..."
	@$(TARGET) $(TEST_DIR)/feature_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running endless loop test..."
	@$(TARGET) $(TEST_DIR)/endless_loop_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running math tests..."
	@$(TARGET) $(TEST_DIR)/math_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running string concatenation tests..."
	@$(TARGET) $(TEST_DIR)/string_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running string manipulation tests..."
	@$(TARGET) $(TEST_DIR)/string_manip_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running increment decrement tests..."
	@$(TARGET) $(TEST_DIR)/increment_decrement_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running file I/O tests..."
	@$(TARGET) $(TEST_DIR)/file_io_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running double tests..."
	@$(TARGET) $(TEST_DIR)/double_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running break/continue tests..."
	@$(TARGET) $(TEST_DIR)/break_continue_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running async I/O tests..."
	@$(TARGET) $(TEST_DIR)/async_io_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running array tests..."
	@$(TARGET) $(TEST_DIR)/array_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running pointer tests..."
	@$(TARGET) $(TEST_DIR)/pointer_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running logical operators tests..."
	@$(TARGET) $(TEST_DIR)/logical_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running comparison operators tests..."
	@$(TARGET) $(TEST_DIR)/comparison_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running functions tests..."
	@$(TARGET) $(TEST_DIR)/functions_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running trigonometry tests..."
	@$(TARGET) $(TEST_DIR)/trig_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running file seek tests..."
	@$(TARGET) $(TEST_DIR)/file_seek_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running include tests..."
	@$(TARGET) $(TEST_DIR)/include_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running nested include tests..."
	@$(TARGET) $(TEST_DIR)/nested_include_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running async/await tests..."
	@$(TARGET) $(TEST_DIR)/async_await_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP step 0 (class skipping)..."
	@$(TARGET) $(TEST_DIR)/oop_step0.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP step 1 (object creation)..."
	@$(TARGET) $(TEST_DIR)/oop_step1.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP field tests..."
	@$(TARGET) $(TEST_DIR)/oop_fields.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP method tests..."
	@$(TARGET) $(TEST_DIR)/oop_method.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP working tests..."
	@$(TARGET) $(TEST_DIR)/oop_working.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP mutation tests..."
	@$(TARGET) $(TEST_DIR)/oop_mutation_test.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "Running OOP advanced tests..."
	@$(TARGET) $(TEST_DIR)/oop_advanced.rc 2>&1 | grep -v "Error at token" || true
	@echo ""
	@echo "=== All Tests Completed ==="

run-feature-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/feature_test.rc

run-endless-loop: $(TARGET)
	$(TARGET) $(TEST_DIR)/endless_loop_test.rc

run-math-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/math_test.rc

run-string-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/string_test.rc

run-string-manip: $(TARGET)
	$(TARGET) $(TEST_DIR)/string_manip_test.rc

run-increment-decrement-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/increment_decrement_test.rc

run-file-io-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/file_io_test.rc

run-double-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/double_test.rc

run-break-continue-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/break_continue_test.rc

run-async-io-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/async_io_test.rc

run-array-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/array_test.rc

run-pointer-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/pointer_test.rc

run-logical-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/logical_test.rc

run-comparison-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/comparison_test.rc

run-functions-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/functions_test.rc

run-trig-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/trig_test.rc

run-file-seek-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/file_seek_test.rc

run-include-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/include_test.rc

run-nested-include-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/nested_include_test.rc

run-async-await-test: $(TARGET)
	$(TARGET) $(TEST_DIR)/async_await_test.rc

run-oop-step0: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_step0.rc

run-oop-step1: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_step1.rc

run-oop-fields: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_fields.rc

run-oop-method: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_method.rc

run-oop-working: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_working.rc

run-oop-mutation: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_mutation_test.rc

run-oop-advanced: $(TARGET)
	$(TARGET) $(TEST_DIR)/oop_advanced.rc

run-http-simple: $(TARGET)
	$(TARGET) $(EXAMPLE_DIR)/http_simple.rc

run-http-persistent: $(TARGET)
	$(TARGET) $(EXAMPLE_DIR)/http_persistent.rc

run-http-multi: $(TARGET)
	$(TARGET) $(EXAMPLE_DIR)/http_multi.rc

run-async-demo: $(TARGET)
	$(TARGET) $(EXAMPLE_DIR)/async_demo.rc

help:
	@echo "RC - Retoor's C Interpreter"
	@echo ""
	@echo "Usage:"
	@echo "  make                  - Build the interpreter"
	@echo "  make test             - Run all feature tests"
	@echo "  make clean            - Remove all build artifacts"
	@echo ""
	@echo "Individual Tests:"
	@echo "  make run-feature-test           - Run feature_test.rc (negative numbers, ==, !=)"
	@echo "  make run-endless-loop           - Run endless_loop_test.rc (while(1) test)"
	@echo "  make run-math-test              - Run math_test.rc (math functions)"
	@echo "  make run-string-test            - Run string_test.rc (string concatenation)"
	@echo "  make run-string-manip           - Run string_manip_test.rc (string manipulation & slicing)"
	@echo "  make run-increment-decrement-test - Run increment_decrement_test.rc (++/--)"
	@echo "  make run-file-io-test           - Run file_io_test.rc (file I/O operations)"
	@echo "  make run-double-test            - Run double_test.rc (double data type)"
	@echo "  make run-break-continue-test    - Run break_continue_test.rc (break/continue)"
	@echo "  make run-async-io-test          - Run async_io_test.rc (async I/O)"
	@echo "  make run-array-test             - Run array_test.rc (arrays)"
	@echo "  make run-pointer-test           - Run pointer_test.rc (pointers & dereference)"
	@echo "  make run-logical-test           - Run logical_test.rc (&&, ||)"
	@echo "  make run-comparison-test        - Run comparison_test.rc (<, >, <=, >=)"
	@echo "  make run-functions-test         - Run functions_test.rc (function calls & recursion)"
	@echo "  make run-trig-test              - Run trig_test.rc (sin, cos, tan)"
	@echo "  make run-file-seek-test         - Run file_seek_test.rc (fseek, ftell)"
	@echo "  make run-include-test           - Run include_test.rc (#include directive)"
	@echo "  make run-nested-include-test    - Run nested_include_test.rc (nested includes)"
	@echo "  make run-async-await-test       - Run async_await_test.rc (async/await syntax)"
	@echo "  make run-oop-step0              - Run oop_step0.rc (class skipping)"
	@echo "  make run-oop-step1              - Run oop_step1.rc (object creation)"
	@echo "  make run-oop-fields             - Run oop_fields.rc (field initialization)"
	@echo "  make run-oop-method             - Run oop_method.rc (method calls)"
	@echo "  make run-oop-working            - Run oop_working.rc (full OOP test)"
	@echo "  make run-oop-mutation           - Run oop_mutation_test.rc (field mutation)"
	@echo "  make run-oop-advanced           - Run oop_advanced.rc (advanced OOP examples)"
	@echo ""
	@echo "Examples:"
	@echo "  make run-http-simple            - Run http_simple.rc (single connection HTTP server)"
	@echo "  make run-http-persistent        - Run http_persistent.rc (persistent HTTP server)"
	@echo "  make run-http-multi             - Run http_multi.rc (HTTP server, 100 connections)"
	@echo "  make run-async-demo             - Run async_demo.rc (comprehensive async I/O demo)"
	@echo ""
	@echo "Directory Structure:"
	@echo "  src/       - Source code files"
	@echo "  tests/     - Test programs (.rc files)"
	@echo "  examples/  - Example programs (.rc files)"
	@echo "  build/     - Compiled object files"
	@echo "  bin/       - Final executable (rc)"
