# DWN - Desktop Window Manager
# Simple Makefile - just run 'make' to build!

# Compiler settings
CC = gcc
CFLAGS = -Wall -Wextra -Wpedantic -Wshadow -O2 -I./include
CFLAGS += -fstack-protector-strong -D_FORTIFY_SOURCE=2
LDFLAGS = -lX11 -lXext -lXinerama -lXrandr -lXft -lfontconfig -ldbus-1 -lcurl -lm -lpthread -lXtst -lXi -ldl

# Directories
SRC_DIR = src
INC_DIR = include
BUILD_DIR = build
BIN_DIR = bin

# Find all source files automatically (including subdirectories)
SRCS = $(shell find $(SRC_DIR) -name '*.c' -type f)
OBJS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRCS))
DEPS = $(OBJS:.o=.d)

# Output binary
TARGET = $(BIN_DIR)/dwn

# Installation paths
PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
DATADIR = $(PREFIX)/share
SYSCONFDIR = /etc

# Get pkg-config flags (with error handling)
PKG_CFLAGS := $(shell pkg-config --cflags x11 xext xinerama xrandr xft fontconfig dbus-1 xtst xi libpng tesseract lept 2>/dev/null)
PKG_LIBS := $(shell pkg-config --libs x11 xext xinerama xrandr xft fontconfig dbus-1 xtst xi libpng tesseract lept 2>/dev/null)

# Use pkg-config if available
ifneq ($(PKG_LIBS),)
    LDFLAGS = $(PKG_LIBS) -lcurl -lm -lpthread
endif
ifneq ($(PKG_CFLAGS),)
    CFLAGS += $(PKG_CFLAGS)
endif

# =============================================================================
# MAIN TARGETS
# =============================================================================

.PHONY: all help clean install uninstall debug sanitize run test deps check-deps

# Default target - show help if first time, otherwise build
all: check-deps $(TARGET)
	@echo ""
	@echo "Build successful! Binary created at: $(TARGET)"
	@echo ""
	@echo "Next steps:"
	@echo "  make run      - Test DWN in a window (safe, doesn't affect your desktop)"
	@echo "  make install  - Install DWN system-wide"
	@echo ""

# Show help
help:
	@echo "=============================================="
	@echo "  DWN - Desktop Window Manager"
	@echo "=============================================="
	@echo ""
	@echo "QUICK START:"
	@echo "  make deps     - Install required dependencies (Ubuntu/Debian)"
	@echo "  make          - Build DWN"
	@echo "  make run      - Test DWN in a safe window"
	@echo "  make install  - Install to your system"
	@echo ""
	@echo "ALL COMMANDS:"
	@echo "  make          - Build DWN (release version)"
	@echo "  make debug    - Build with debug symbols"
	@echo "  make sanitize - Build with address/UB sanitizers"
	@echo "  make run      - Test in Xephyr window (safe!)"
	@echo "  make install  - Install to $(BINDIR)"
	@echo "  make uninstall- Remove from system"
	@echo "  make clean    - Remove build files"
	@echo "  make deps     - Install dependencies (needs sudo)"
	@echo "  make help     - Show this help"
	@echo ""
	@echo "API TESTING:"
	@echo "  make test         - Run API integration tests"
	@echo "  make test-quick   - Run quick tests (skip OCR)"
	@echo "  make test-coverage- Run tests with coverage report"
	@echo ""
	@echo "AFTER INSTALL:"
	@echo "  1. Log out of your current session"
	@echo "  2. At login screen, select 'DWN' as your session"
	@echo "  3. Log in and enjoy!"
	@echo ""

# =============================================================================
# BUILD TARGETS
# =============================================================================

# Build with debug symbols
debug: CFLAGS += -g -DDEBUG
debug: clean $(TARGET)
	@echo "Debug build complete!"

# Build with address and undefined behavior sanitizers
sanitize: CFLAGS += -g -fsanitize=address,undefined -fno-omit-frame-pointer
sanitize: LDFLAGS += -fsanitize=address,undefined
sanitize: clean $(TARGET)
	@echo "Sanitizer build complete!"
	@echo "Run with: ASAN_OPTIONS=detect_leaks=1 ./$(TARGET)"

# Link all object files into final binary
$(TARGET): $(OBJS) | $(BIN_DIR)
	@echo "Linking..."
	@$(CC) $(OBJS) -o $@ $(LDFLAGS)

# Compile each source file
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
	@echo "Compiling $<..."
	@mkdir -p $(dir $@)
	@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@

# Create build directory
$(BUILD_DIR):
	@mkdir -p $(BUILD_DIR)

# Create bin directory
$(BIN_DIR):
	@mkdir -p $(BIN_DIR)

# Include dependency files
-include $(DEPS)

# =============================================================================
# INSTALL / UNINSTALL
# =============================================================================

install: $(TARGET)
	@echo "Installing DWN..."
	@install -Dm755 $(TARGET) $(DESTDIR)$(BINDIR)/dwn
	@install -Dm644 examples/dwn.desktop $(DESTDIR)$(DATADIR)/xsessions/dwn.desktop
	@mkdir -p $(DESTDIR)$(SYSCONFDIR)/dwn
	@install -Dm644 config/config.example $(DESTDIR)$(SYSCONFDIR)/dwn/config.example
	@echo ""
	@echo "=============================================="
	@echo "  Installation complete!"
	@echo "=============================================="
	@echo ""
	@echo "To configure DWN, run:"
	@echo "  mkdir -p ~/.config/dwn"
	@echo "  cp $(SYSCONFDIR)/dwn/config.example ~/.config/dwn/config"
	@echo ""
	@echo "Then log out and select 'DWN' at the login screen!"
	@echo ""

uninstall:
	@echo "Removing DWN..."
	@rm -f $(DESTDIR)$(BINDIR)/dwn
	@rm -f $(DESTDIR)$(DATADIR)/xsessions/dwn.desktop
	@rm -rf $(DESTDIR)$(SYSCONFDIR)/dwn
	@echo "DWN has been uninstalled."

# =============================================================================
# DEVELOPMENT / TESTING
# =============================================================================

# Test DWN in a nested X server (safe - doesn't touch your desktop)
run: $(TARGET)
	@echo "Starting DWN in test mode..."
	@echo "(Press Alt+Shift+Q inside the window to quit)"
	Xephyr :1 -screen 1280x720 &
	sleep 1
	DISPLAY=:1 $(TARGET)

# Clean build files
clean:
	@echo "Cleaning build files..."
	@rm -rf $(BUILD_DIR) $(BIN_DIR)
	@echo "Clean complete."

# =============================================================================
# DEPENDENCY MANAGEMENT
# =============================================================================

# Check if dependencies are installed
check-deps:
	@command -v pkg-config >/dev/null 2>&1 || { \
		echo "ERROR: pkg-config is not installed!"; \
		echo "Run: make deps"; \
		exit 1; \
	}
	@pkg-config --exists x11 2>/dev/null || { \
		echo "ERROR: X11 development libraries not found!"; \
		echo "Run: make deps"; \
		exit 1; \
	}
	@pkg-config --exists dbus-1 2>/dev/null || { \
		echo "ERROR: D-Bus development libraries not found!"; \
		echo "Run: make deps"; \
		exit 1; \
	}

# Install dependencies (Ubuntu/Debian)
deps:
	@echo "Installing dependencies..."
	@echo "This requires sudo (administrator) access."
	@echo ""
	@if command -v apt >/dev/null 2>&1; then \
		sudo apt update && sudo apt install -y \
			build-essential \
			pkg-config \
			libx11-dev \
			libxext-dev \
			libxinerama-dev \
			libxrandr-dev \
			libxft-dev \
			libxtst-dev \
			libfontconfig1-dev \
			libdbus-1-dev \
			libcurl4-openssl-dev \
			libpng-dev \
			libtesseract-dev \
			libleptonica-dev \
			tesseract-ocr \
			tesseract-ocr-eng \
			xserver-xephyr \
			dmenu; \
		echo ""; \
		echo "Dependencies installed successfully!"; \
		echo "Now run: make"; \
	elif command -v dnf >/dev/null 2>&1; then \
		sudo dnf install -y \
			gcc make \
			pkg-config \
			libX11-devel \
			libXext-devel \
			libXinerama-devel \
			libXrandr-devel \
			libXtst-devel \
			dbus-devel \
			libcurl-devel \
			libpng-devel \
			tesseract-devel \
			leptonica-devel \
			tesseract-langpack-eng \
			xorg-x11-server-Xephyr \
			dmenu; \
		echo ""; \
		echo "Dependencies installed successfully!"; \
		echo "Now run: make"; \
	elif command -v pacman >/dev/null 2>&1; then \
		sudo pacman -S --needed \
			base-devel \
			pkg-config \
			libx11 \
			libxext \
			libxinerama \
			libxrandr \
			libxtst \
			dbus \
			curl \
			libpng \
			tesseract \
			tesseract-data-eng \
			leptonica \
			xorg-server-xephyr \
			dmenu; \
		echo ""; \
		echo "Dependencies installed successfully!"; \
		echo "Now run: make"; \
	else \
		echo "ERROR: Could not detect package manager!"; \
		echo "Please install these packages manually:"; \
		echo "  - GCC and Make"; \
		echo "  - pkg-config"; \
		echo "  - X11, Xext, Xinerama, Xrandr, Xtst development libraries"; \
		echo "  - D-Bus development library"; \
		echo "  - libcurl development library"; \
		echo "  - Xephyr (for testing)"; \
		echo "  - dmenu (for app launcher)"; \
		exit 1; \
	fi

# =============================================================================
# API INTEGRATION TESTS
# =============================================================================

TEST_PORT ?= 18777
TEST_DISPLAY ?= :99

.PHONY: test test-quick test-coverage test-isolated

test:
	@echo "Running API integration tests..."
	@echo "Note: DWN must be running with API enabled (port 8777)"
	@cd tests && python -m pytest -v

test-quick:
	@echo "Running quick API tests (skipping OCR)..."
	@cd tests && python -m pytest -v -x --ignore=test_ocr_commands.py

test-coverage:
	@echo "Running API tests with coverage..."
	@cd tests && python -m pytest --cov=. --cov-report=term-missing

test-isolated: $(TARGET)
	@echo "Starting isolated DWN test instance on port $(TEST_PORT)..."
	@-kill $$(cat /tmp/dwn_test_dwn.pid 2>/dev/null) 2>/dev/null; true
	@-kill $$(cat /tmp/dwn_test_xephyr.pid 2>/dev/null) 2>/dev/null; true
	@rm -f /tmp/dwn_test_xephyr.pid /tmp/dwn_test_dwn.pid /tmp/dwn_test.log
	@sleep 1
	@Xephyr $(TEST_DISPLAY) -screen 1280x720 2>/dev/null & echo $$! > /tmp/dwn_test_xephyr.pid
	@sleep 2
	@DISPLAY=$(TEST_DISPLAY) $(TARGET) -p $(TEST_PORT) > /tmp/dwn_test.log 2>&1 & echo $$! > /tmp/dwn_test_dwn.pid
	@sleep 3
	@for i in 1 2 3 4 5; do \
		if curl -s http://localhost:$(TEST_PORT)/api/status >/dev/null 2>&1; then \
			echo "DWN API ready on port $(TEST_PORT)"; \
			break; \
		fi; \
		echo "Waiting for DWN API... ($$i/5)"; \
		sleep 1; \
	done
	@if ! curl -s http://localhost:$(TEST_PORT)/api/status >/dev/null 2>&1; then \
		echo "ERROR: DWN API not responding. Check /tmp/dwn_test.log"; \
		cat /tmp/dwn_test.log 2>/dev/null | tail -50; \
		kill $$(cat /tmp/dwn_test_dwn.pid 2>/dev/null) 2>/dev/null || true; \
		kill $$(cat /tmp/dwn_test_xephyr.pid 2>/dev/null) 2>/dev/null || true; \
		exit 1; \
	fi
	@DWN_TEST_PORT=$(TEST_PORT) python -m pytest tests/ -v; \
	EXIT_CODE=$$?; \
	kill $$(cat /tmp/dwn_test_dwn.pid 2>/dev/null) 2>/dev/null || true; \
	kill $$(cat /tmp/dwn_test_xephyr.pid 2>/dev/null) 2>/dev/null || true; \
	rm -f /tmp/dwn_test_xephyr.pid /tmp/dwn_test_dwn.pid; \
	exit $$EXIT_CODE

# =============================================================================
# CODE QUALITY (for developers)
# =============================================================================

.PHONY: format check

format:
	@echo "Formatting code..."
	@clang-format -i $(SRC_DIR)/*.c $(INC_DIR)/*.h 2>/dev/null || \
		echo "Note: clang-format not installed (optional)"

check:
	@echo "Running static analysis..."
	@cppcheck --enable=all --inconclusive -I$(INC_DIR) $(SRC_DIR) 2>/dev/null || \
		echo "Note: cppcheck not installed (optional)"
