# === Config ===
TARGET       := boot/espresso.elf
ISO          := boot/espresso.iso
FAT16_DISK   := espresso.img
CC           := i686-elf-gcc
AS           := i686-elf-as
NASM         := nasm
QEMU_MKE_IMG := qemu-img create -f raw $(FAT16_DISK) 64M
MKFS_VFAT    := sudo mkfs.vfat
MKFS_FLAGS   := -F 16 -S 512
NASMFLAGS    := -f elf32
WNOFLAGS     := -Wno-discarded-qualifiers
CFLAGS       := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) -nostdlib -nostartfiles -include include/kincl.h
LDFLAGS      := -T linker.ld -ffreestanding -O2 -nostdlib -nostartfiles
QEMUFLAGS    := -no-shutdown -drive file=$(FAT16_DISK),format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1
QEMUFLGS_EXT := -vga std
MOR_QEMUFLGS := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 -serial file:serial.log
QEMU_BOOT_FLG := -boot d -cdrom $(ISO)
QEMU_BOOT_RPI := -kernel $(TARGET)
SRC_DIRS     := kernel drivers lib
INCLUDE_DIRS := include
ARCH_DIR     := arch
X86_ARCH_DIR := $(ARCH_DIR)/x86
X86_BOOT_DIR := $(X86_ARCH_DIR)/boot
INCLUDES     := $(addprefix -I, $(INCLUDE_DIRS))
ISO_DIR      := isodir
BOOT_DIR     := $(ISO_DIR)/boot
GRUB_DIR     := $(BOOT_DIR)/grub
GRUB_CFG     := grub.cfg

# === Host checks ===
IS_RPI        := $(shell [ -f /proc/device-tree/model ] && grep -qi "Raspberry Pi" /proc/device-tree/model && echo 1 || echo 0)

# === File collection ===
C_SRCS       := $(foreach dir, $(SRC_DIRS), $(shell find $(dir) -name '*.c'))
S_SRCS       := $(foreach dir, $(ARCH_DIR), $(shell find $(dir) -name '*.s'))
NASM_SRCS    := $(foreach dir, $(ARCH_DIR), $(shell find $(dir) -name '*.asm'))
CRTI_OBJ     := crti.o
CRTBEGIN_OBJ := $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
CRTEND_OBJ   := $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)
CRTN_OBJ     := crtn.o
OBJS         := $(C_SRCS:.c=.o) $(S_SRCS:.s=.o) $(NASM_SRCS:.asm=.o)

OBJ_LINK_LIST := $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(OBJS) $(CRTEND_OBJ) $(CRTN_OBJ)
INTERNAL_OBJS := $(CRTI_OBJ) $(OBJS) $(CRTN_OBJ)

# === Build all targets ===
build: all iso run

# === Build all targets and clean ===
buildc: all iso run clean

# === Default target ===
all: $(TARGET)

# === Debug build ===
debug:
	$(MAKE) clean
	$(MAKE) CFLAGS="$(CFLAGS) -D_DEBUG" $(TARGET)

# === Linking ===
$(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST))
	@mkdir -p $(dir $@)
	$(CC) $(LDFLAGS) -o $@ $^ -lgcc

# === Compiling C files ===
%.o: %.c
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

# === Assembling S files ===
%.o: %.s
	$(AS) $< -o $@
	
%.o: %.asm
	$(NASM) $(NASMFLAGS) $< -o $@

# === ISO generation ===
iso: $(TARGET)
	@grub-file --is-x86-multiboot $(TARGET) && echo "multiboot confirmed" || (echo "not multiboot" && exit 1)
	mkdir -p $(GRUB_DIR)
	cp $(TARGET) $(BOOT_DIR)
ifneq ($(IS_RPI),1)
	cp $(GRUB_CFG) $(GRUB_DIR)
	grub-mkrescue -o $(ISO) $(ISO_DIR)
endif

# === Run in QEMU ===
run: iso
	@if [ ! -f $(FAT16_DISK) ]; then \
		$(QEMU_MKE_IMG); \
		sudo mkfs.fat $(MKFS_FLAGS) espresso.img; \
	fi
	@echo $(IS_RPI)
ifeq ($(IS_RPI),1)
	qemu-system-i386 $(QEMU_BOOT_RPI) $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
else
	qemu-system-i386 $(QEMU_BOOT_FLG) $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
endif


# === Clean all build artifacts ===
clean:
	rm -f $(INTERNAL_OBJS) $(TARGET) $(ISO)
	rm -rf $(ISO_DIR)

clean_disk:
	rm -f espresso.img

# === Push code to repo ===
commit:
ifndef MSG
	$(error MSG required)
endif
ifndef RELEASENUM
	$(error RELEASENUM required)
endif
	git add .
	git commit -m "$(MSG)"
	git push origin main

	git tag -a "$(RELEASENUM)" -m "Espresso $(RELEASENUM)"
	git push origin "$(RELEASENUM)"

.PHONY: all clean clean_disk iso run debug build buildc
