# Makefile for ft_ping
# Uses build.mk generated by ./configure script

# Configuration

# Include generated configuration (must run ./configure first)
-include build.mk

# Check if build.mk exists
ifeq ($(wildcard build.mk),)
$(error build.mk not found. Please run './configure' first)
endif

# Project Configuration

NAME = ft_ping
TEST_BIN = ft_ping.test
VERSION := 0.0.1
BUILD_DATE := $(shell git log -1 --format=%cd --date=format:'%Y-%m-%d %H:%M:%S' 2>/dev/null || date -u '+%Y-%m-%d %H:%M:%S')
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "nogit")

ifeq ($(GIT_COMMIT),nogit)
    HAS_GIT_COMMIT=0
else
    HAS_GIT_COMMIT=1
endif

.DEFAULT_GOAL := all
MAKEFLAGS += --no-print-directory

BINARIES = ft_ping
# Future: BINARIES = ft_ping ft_traceroute

# Include source files
include sources/ping.mk

SRCS = $(PING_SRCS)
TESTS = $(PING_TESTS)

# Get libicmp sources for dependency tracking if building locally
ifeq ($(BUILD_LOCAL_LIBICMP),yes)
LIBICMP_SRCS = $(shell find $(LIBICMP_DIR)/src -type f -name '*.c' 2>/dev/null)
LIBICMP_HEADERS = $(wildcard $(LIBICMP_DIR)/includes/*.h)
endif

# Build Directories
OBJ_DIR = build
OBJS = $(SRCS:src/%.c=$(OBJ_DIR)/%.o)
DEPS = $(OBJS:.o=.d)

# Build Rules

VERSION_HEADER = includes/version_gen.h

$(VERSION_HEADER): FORCE
	@$(MAKE) --no-print-directory update-version-header

.PHONY: update-version-header
update-version-header:
	@NEW_HEADER=$$(mktemp); \
	echo "/* Auto-generated - DO NOT EDIT */" > $$NEW_HEADER; \
	echo "#ifndef PING_VERSION_GEN_H" >> $$NEW_HEADER; \
	echo "#define PING_VERSION_GEN_H" >> $$NEW_HEADER; \
	echo "#define PING_VERSION \"$(VERSION)\"" >> $$NEW_HEADER; \
	echo "#define PING_BUILD_DATE \"$(BUILD_DATE)\"" >> $$NEW_HEADER; \
	echo "#define PING_GIT_COMMIT \"$(GIT_COMMIT)\"" >> $$NEW_HEADER; \
	echo "#define PING_HAS_GIT_COMMIT $(HAS_GIT_COMMIT)" >> $$NEW_HEADER; \
	echo "" >> $$NEW_HEADER; \
	echo "typedef struct s_prog_name" >> $$NEW_HEADER; \
	echo "{" >> $$NEW_HEADER; \
	echo "	char		*alloc;" >> $$NEW_HEADER; \
	echo "	const char	*name;" >> $$NEW_HEADER; \
	echo "}	t_prog_name;" >> $$NEW_HEADER; \
	echo "" >> $$NEW_HEADER; \
	echo "extern t_prog_name g_prog_name;" >> $$NEW_HEADER; \
	echo "" >> $$NEW_HEADER; \
	echo "#endif" >> $$NEW_HEADER; \
	if [ ! -f $(VERSION_HEADER) ] || ! cmp -s $$NEW_HEADER $(VERSION_HEADER); then \
		mv $$NEW_HEADER $(VERSION_HEADER); \
		echo "[OK] Version header generated"; \
	else \
		rm -f $$NEW_HEADER; \
	fi

FORCE:
.PHONY: FORCE

.PHONY: all
all: $(LIBICMP_DEP) $(VERSION_HEADER) $(NAME)

# Build local libicmp if needed
ifeq ($(BUILD_LOCAL_LIBICMP),yes)
$(LIBICMP_DEP): $(LIBICMP_SRCS) $(LIBICMP_HEADERS)
	@echo "[BUILD] Building local libicmp..."
	$(MAKE) -C $(LIBICMP_DIR) -f $(LIBICMP_MAKEFILE) $(LIBICMP_BUILD_FLAGS)
	@echo "[OK] libicmp built successfully"
endif

# Link ft_ping
$(NAME): $(OBJS) $(LIBICMP_DEP)
	$(CC) -o $@ $(OBJS) $(LDFLAGS)
	@echo "[OK] $(NAME) built successfully"

# Compile object files
$(OBJ_DIR)/%.o: src/%.c
	@mkdir -p $(dir $@)
	$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@

# Include dependencies
-include $(DEPS)

# Test Rules

.PHONY: test
ifeq ($(ENABLE_TESTS),yes)
test: $(TEST_BIN)
	@echo "[TEST] Running tests..."
ifeq ($(SUDO_TESTS),yes)
	@if [ "$$(id -u)" -ne 0 ]; then \
		echo "[WARN] Tests require root privileges, using sudo..."; \
		sudo ./$(TEST_BIN); \
	else \
		./$(TEST_BIN); \
	fi
else
	./$(TEST_BIN)
endif
	@echo "[OK] All tests passed"


$(TEST_BIN): $(VERSION_HEADER) $(TESTS) $(filter-out $(OBJ_DIR)/ping/main.o,$(OBJS)) $(LIBICMP_DEP)
	@mkdir -p $(dir $@)
	@echo "[BUILD] Building test binary..."
	$(CC) $(CPPFLAGS) $(CFLAGS) $(filter-out $(VERSION_HEADER),$^) $(LDFLAGS) $(TEST_LDFLAGS) -o $@
else
test:
	@echo "[SKIP] Tests are disabled"
	@echo "Run './configure --enable-tests' to enable tests"
endif

# Installation Rules

.PHONY: install
install: all
	@echo "[INSTALL] Installing $(NAME)..."
ifeq ($(BUILD_LOCAL_LIBICMP),yes)
ifeq ($(INSTALL_LIBICMP),yes)
	@echo "[INSTALL] Installing libicmp to $(LIBICMP_PREFIX)..."
	$(MAKE) -C $(LIBICMP_DIR) -f $(LIBICMP_MAKEFILE) install PREFIX=$(LIBICMP_PREFIX)
	@echo "[OK] libicmp installed"
endif
endif
	@echo "[INSTALL] Installing binary to $(BINDIR)..."
	install -d $(DESTDIR)$(BINDIR)
	install -m 755 $(NAME) $(DESTDIR)$(BINDIR)/$(NAME)
	@echo "[OK] $(NAME) installed to $(BINDIR)/$(NAME)"
	@echo ""
	@echo "Installation complete!"
	@echo "Run: $(BINDIR)/$(NAME)"

.PHONY: uninstall
uninstall:
	@echo "[UNINSTALL] Removing $(NAME)..."
	$(RM) $(DESTDIR)$(BINDIR)/$(NAME)
	@echo "[OK] $(NAME) removed"
ifeq ($(BUILD_LOCAL_LIBICMP),yes)
ifeq ($(INSTALL_LIBICMP),yes)
	@echo "[UNINSTALL] Removing libicmp..."
	$(MAKE) -C $(LIBICMP_DIR) -f $(LIBICMP_MAKEFILE) uninstall PREFIX=$(LIBICMP_PREFIX)
	@echo "[OK] libicmp removed"
endif
endif

# Clean Rules

.PHONY: clean
clean:
	@echo "[CLEAN] Cleaning object files..."
	$(RM) $(VERSION_HEADER)
	$(RM) -r $(OBJ_DIR)
ifeq ($(BUILD_LOCAL_LIBICMP),yes)
	@echo "[CLEAN] Cleaning libicmp..."
	$(MAKE) -C $(LIBICMP_DIR) -f $(LIBICMP_MAKEFILE) clean
endif
	@echo "[OK] Clean complete"

.PHONY: fclean
fclean: clean
	@echo "[FCLEAN] Removing binaries..."
	$(RM) $(NAME)
	$(RM) $(TEST_BIN)
ifeq ($(BUILD_LOCAL_LIBICMP),yes)
	@echo "[FCLEAN] Cleaning libicmp binaries..."
	$(MAKE) -C $(LIBICMP_DIR) -f $(LIBICMP_MAKEFILE) fclean
endif
	@echo "[OK] Full clean complete"

.PHONY: re
re: fclean
	$(MAKE) all

# Configuration Management

.PHONY: reconfigure
reconfigure:
	@echo "[INFO] Removing build.mk..."
	$(RM) build.mk
	@echo "[INFO] Please run './configure' again"

.PHONY: distclean
distclean: fclean
	@echo "[DISTCLEAN] Removing generated configuration..."
	$(RM) build.mk
	@echo "[OK] Distribution clean complete"


# Information Rules


.PHONY: info
info:
	@echo "======================================"
	@echo "Build Configuration for $(NAME)"
	@echo "======================================"
	@echo ""
	@echo "libicmp:"
	@echo " Source:             $(if $(filter yes,$(USE_SYSTEM_LIBICMP)),system,local)"
	@echo " Type:               $(LIBICMP_TYPE)"
	@echo " Path:               $(LIBICMP_PATH)"
	@echo " Build local:        $(BUILD_LOCAL_LIBICMP)"
	@echo " Install to system:  $(INSTALL_LIBICMP)"
	@echo ""
	@echo "Compiler:"
	@echo " CC:                 $(CC)"
	@echo " CPPFLAGS:           $(CPPFLAGS)"
	@echo " CFLAGS:             $(CFLAGS)"
	@echo " LDFLAGS:            $(LDFLAGS)"
	@echo ""
	@echo "Build Options:"
	@echo " Debug:              $(ENABLE_DEBUG)"
	@echo " Sanitizers:         $(ENABLE_SANITIZERS)"
	@echo " LTO:                $(ENABLE_LTO)"
	@echo " Strict:             $(ENABLE_STRICT)"
	@echo " Tests:              $(ENABLE_TESTS)"
	@echo ""
	@echo "Installation:"
	@echo " PREFIX:             $(PREFIX)"
	@echo " BINDIR:             $(BINDIR)"
	@echo " LIBDIR:             $(LIBDIR)"
	@echo " INCLUDEDIR:         $(INCLUDEDIR)"
	@echo ""
	@echo "Run './configure --help' to reconfigure"

.PHONY: help
help:
	@echo "Available targets:"
	@echo ""
	@echo " make or make all  Build ft_ping"
	@echo " make test         Run tests (if enabled)"
	@echo " make install      Install to PREFIX ($(PREFIX))"
	@echo " make uninstall    Uninstall from system"
	@echo " make clean        Remove object files"
	@echo " make fclean       Remove all built files"
	@echo " make re           Rebuild everything"
	@echo " make reconfigure  Remove build.mk (run ./configure again)"
	@echo " make distclean    Full clean including build.mk"
	@echo " make info         Show build configuration"
	@echo " make help         Show this help"
	@echo ""
	@echo "Note: Run './configure' first to generate build.mk"

# vim: tabstop=8 shiftwidth=8 noexpandtab
