CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -Werror -pedantic -Iinclude
DEBUG_FLAGS := -O0 -g3
RELEASE_FLAGS := -O3 -DNDEBUG
LDFLAGS := -lm -lpthread

SRC_DIR := src
TEST_DIR := tests
BUILD_DIR := build
OBJ_DIR := $(BUILD_DIR)/obj
BIN_DIR := $(BUILD_DIR)/bin

CORE_SRCS := $(SRC_DIR)/stats.c \
             $(SRC_DIR)/metrics.c \
             $(SRC_DIR)/concept_drift.c \
             $(SRC_DIR)/data_drift.c \
             $(SRC_DIR)/parallel_drift.c
CLI_SRC := $(SRC_DIR)/drift_cli.c
TEST_SRCS := $(TEST_DIR)/test_runner.c \
             $(TEST_DIR)/test_stats.c \
             $(TEST_DIR)/test_concept_drift.c \
             $(TEST_DIR)/test_data_drift.c \
             $(TEST_DIR)/test_parallel_drift.c

CORE_OBJS := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(CORE_SRCS))
CLI_OBJ := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(CLI_SRC))
TEST_OBJS := $(patsubst $(TEST_DIR)/%.c,$(OBJ_DIR)/tests_%.o,$(TEST_SRCS))

.PHONY: all debug release shared test run clean

all: debug

debug: CFLAGS += $(DEBUG_FLAGS)
debug: $(BIN_DIR)/monitor_drift_cli

release: CFLAGS += $(RELEASE_FLAGS)
release: $(BIN_DIR)/monitor_drift_cli

shared: CFLAGS += $(RELEASE_FLAGS)
shared: $(BIN_DIR)/libmonitor_core.so

$(BIN_DIR)/monitor_drift_cli: $(CORE_OBJS) $(CLI_OBJ) | $(BIN_DIR)
	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)

$(BIN_DIR)/libmonitor_core.so: $(CORE_SRCS) | $(BIN_DIR)
	$(CC) $(CFLAGS) -fPIC -shared $^ -o $@ $(LDFLAGS)

$(BIN_DIR)/monitor_drift_tests: CFLAGS += $(DEBUG_FLAGS)
$(BIN_DIR)/monitor_drift_tests: $(CORE_OBJS) $(TEST_OBJS) | $(BIN_DIR)
	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)

test: $(BIN_DIR)/monitor_drift_tests
	$(BIN_DIR)/monitor_drift_tests

run: debug
	$(BIN_DIR)/monitor_drift_cli

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
	$(CC) $(CFLAGS) -c $< -o $@

$(OBJ_DIR)/tests_%.o: $(TEST_DIR)/%.c | $(OBJ_DIR)
	$(CC) $(CFLAGS) -c $< -o $@

$(BIN_DIR):
	mkdir -p $(BIN_DIR)

$(OBJ_DIR):
	mkdir -p $(OBJ_DIR)

clean:
	rm -rf $(BUILD_DIR)
