CC := gcc

BINARY := unmine
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
PACKAGE := $(BINARY)-$(GIT_VERSION)
GUI_PACKAGE := $(PACKAGE)-gui
TUI_PACKAGE := $(PACKAGE)-tui

BUILD_DIR := build
SOURCE_DIR := src

CFLAGS       := -std=c99 -Wall -Wextra -Wpedantic -Wformat=2 -Wmissing-prototypes -Wshadow -Wstrict-prototypes -DGIT_VERSION="$(GIT_VERSION)" -O3 -flto
GUI_CFLAGS   := `pkg-config --cflags gtk+-3.0`
TUI_CFLAGS   :=
DEBUG_CFLAGS := -g -Og -fno-lto

LDFLAGS     := -lconfig -lpthread
GUI_LDFLAGS := `pkg-config --libs gtk+-3.0`
TUI_LDFLAGS := -lncursesw

CORE_SOURCES := $(SOURCE_DIR)/board.c $(wildcard $(SOURCE_DIR)/classic*.c) $(wildcard $(SOURCE_DIR)/flags*.c) $(SOURCE_DIR)/tile.c $(SOURCE_DIR)/unmine.c
GUI_SOURCES  := $(wildcard $(SOURCE_DIR)/gui*.c)
TUI_SOURCES  := $(wildcard $(SOURCE_DIR)/tui*.c)
CORE_OBJECTS := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(CORE_SOURCES))
GUI_OBJECTS  := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(GUI_SOURCES))
TUI_OBJECTS  := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(TUI_SOURCES))

SOURCES  := $(CORE_SOURCES) $(GUI_SOURCES) $(TUI_SOURCES)
HEADERS  := $(wildcard $(SOURCE_DIR)/*.h)
ASSETS   := icons
ICON_PNG := icons/64x64/flag.png
DOCS     := ICON-LICENSE INSTALL LICENSE NEWS README
OTHERS   := Makefile $(wildcard packaging/*)

MINGW_DIR := C:/msys64/mingw64
CORE_DLLS := libconfig-11 libwinpthread-1
GUI_DLLS := libatk-1.0-0 libbz2-1 libcairo-2 libcairo-gobject-2 libepoxy-0 libexpat-1 libffi-6 \
libfontconfig-1 libfreetype-6 libfribidi-0 libgcc_s_seh-1 libgdk_pixbuf-2.0-0 libgdk-3-0 \
libgio-2.0-0 libglib-2.0-0 libgmodule-2.0-0 libgobject-2.0-0 libgraphite2 libgtk-3-0 \
libharfbuzz-0 libiconv-2 libintl-8 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 \
libpangowin32-1.0-0 libpcre-1 libpixman-1-0 libpng16-16 libstdc++-6 zlib1
ifdef COMSPEC
	TUI_CFLAGS += -I$(MINGW_DIR)/include/ncursesw
	GUI_LDFLAGS += -Wl,--subsystem,windows
	CORE_OBJECTS += $(BUILD_DIR)/icon.res
endif

all: gui tui

debug: CFLAGS += $(DEBUG_CFLAGS)
debug: all

$(BUILD_DIR)/board.o: $(SOURCE_DIR)/board.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/classic.o: $(SOURCE_DIR)/classic.h $(SOURCE_DIR)/board.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/classic_config.o: $(SOURCE_DIR)/classic_config.h $(SOURCE_DIR)/classic.h
$(BUILD_DIR)/flags.o: $(SOURCE_DIR)/flags.h $(SOURCE_DIR)/board.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/flags_ai.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/flags_ai.o: $(SOURCE_DIR)/flags_ai.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/flags.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/flags_config.o: $(SOURCE_DIR)/flags_config.h $(SOURCE_DIR)/flags.h $(SOURCE_DIR)/flags_ai.h
$(BUILD_DIR)/gui.o: $(SOURCE_DIR)/gui.h $(SOURCE_DIR)/gui_classic.h $(SOURCE_DIR)/gui_flags.h $(SOURCE_DIR)/unmine.h
$(BUILD_DIR)/gui_board.o: $(SOURCE_DIR)/gui_board.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/gui_classic.o: $(SOURCE_DIR)/gui_classic.h $(SOURCE_DIR)/classic.h $(SOURCE_DIR)/classic_config.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/gui.h $(SOURCE_DIR)/gui_board.h $(SOURCE_DIR)/gui_params.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/gui_flags.o: $(SOURCE_DIR)/gui_flags.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/flags.h $(SOURCE_DIR)/flags_ai.h $(SOURCE_DIR)/flags_config.h $(SOURCE_DIR)/gui.h $(SOURCE_DIR)/gui_board.h $(SOURCE_DIR)/gui_params.h $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/tile.o: $(SOURCE_DIR)/tile.h
$(BUILD_DIR)/tui.o: $(SOURCE_DIR)/board.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/tile.h $(SOURCE_DIR)/tui_classic.h $(SOURCE_DIR)/tui_common.h $(SOURCE_DIR)/tui_flags.h $(SOURCE_DIR)/unmine.h
$(BUILD_DIR)/tui_classic.o: $(SOURCE_DIR)/tui_classic.h $(SOURCE_DIR)/classic.h $(SOURCE_DIR)/classic_config.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/tile.h $(SOURCE_DIR)/tui_common.h
$(BUILD_DIR)/tui_common.o: $(SOURCE_DIR)/tui_common.h $(SOURCE_DIR)/unmine.h
$(BUILD_DIR)/tui_flags.o: $(SOURCE_DIR)/tui_flags.h $(SOURCE_DIR)/coords.h $(SOURCE_DIR)/flags.h $(SOURCE_DIR)/flags_ai.h $(SOURCE_DIR)/flags_config.h $(SOURCE_DIR)/tile.h $(SOURCE_DIR)/tui_common.h
$(BUILD_DIR)/unmine.o: $(SOURCE_DIR)/unmine.h

clean:
	@$(RM) -f $(BUILD_DIR)/$(BINARY)-gui $(BUILD_DIR)/$(BINARY)-tui $(BUILD_DIR)/$(BINARY)-gui.exe $(BUILD_DIR)/$(BINARY)-tui.exe
	@$(RM) -f $(CORE_OBJECTS) $(GUI_OBJECTS) $(TUI_OBJECTS) $(BUILD_DIR)/icon.ico
	@$(RM) -f $(BUILD_DIR)/$(PACKAGE).tar.gz $(BUILD_DIR)/$(PACKAGE)-setup.exe
	@$(RM) -f $(BUILD_DIR)/$(GUI_PACKAGE).zip $(BUILD_DIR)/$(TUI_PACKAGE).zip

cppcheck:
	cppcheck --enable=all --std=c89 --quiet $(SOURCE_DIR)

dist: $(BUILD_DIR)/$(PACKAGE).tar.gz

dist-windows-gui: $(BUILD_DIR)/$(GUI_PACKAGE).zip

dist-windows-installer: $(BUILD_DIR)/$(PACKAGE)-setup.exe

dist-windows-tui: $(BUILD_DIR)/$(TUI_PACKAGE).zip

gui: $(BUILD_DIR)/$(BINARY)-gui

gui-debug: CFLAGS += $(DEBUG_CFLAGS)
gui-debug: $(BUILD_DIR)/$(BINARY)-gui

todo:
	grep -Fn TODO $(SOURCES) $(HEADERS)

tui: $(BUILD_DIR)/$(BINARY)-tui

tui-debug: CFLAGS += $(DEBUG_CFLAGS)
tui-debug: $(BUILD_DIR)/$(BINARY)-tui

$(BUILD_DIR)/$(BINARY)-gui: CFLAGS += $(GUI_CFLAGS)
$(BUILD_DIR)/$(BINARY)-gui: $(CORE_OBJECTS) $(GUI_OBJECTS)
	@$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(GUI_LDFLAGS)

$(BUILD_DIR)/$(BINARY)-tui: CFLAGS += $(TUI_CFLAGS)
$(BUILD_DIR)/$(BINARY)-tui: $(CORE_OBJECTS) $(TUI_OBJECTS)
	@$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(TUI_LDFLAGS)

$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c
	@$(CC) $(CFLAGS) -c $< -o $@

$(BUILD_DIR)/icon.ico: $(ICON_PNG)
	@icotool --create --icon --output=$@ $<

$(BUILD_DIR)/icon.res: $(BUILD_DIR)/icon.ico
	@echo "0 ICON \"$<\"" | windres --output-format coff --output $@

$(BUILD_DIR)/$(PACKAGE).tar.gz: $(SOURCES) $(HEADERS) $(ASSETS) $(DOCS) $(OTHERS)
	tar --transform "s,^,$(PACKAGE)/," -czf $@ $^

$(BUILD_DIR)/$(PACKAGE)-setup.exe: packaging/windows_installer.nsi all $(ASSETS) $(DOCS)
	makensis -V4 -NOCD -DBUILD_DIR=$(BUILD_DIR) -DNAME=$(BINARY) -DVERSION=$(GIT_VERSION) -DMINGW_DIR=$(MINGW_DIR) $<

$(BUILD_DIR)/$(GUI_PACKAGE).zip: $(BUILD_DIR)/$(BINARY)-gui $(ASSETS) $(DOCS)
	mkdir -p $(BUILD_DIR)/$(GUI_PACKAGE)
	cp ICON-LICENSE $(BUILD_DIR)/$(GUI_PACKAGE)/ICON-LICENSE.txt
	cp LICENSE $(BUILD_DIR)/$(GUI_PACKAGE)/LICENSE.txt
	cp NEWS $(BUILD_DIR)/$(GUI_PACKAGE)/NEWS.txt
	cp README $(BUILD_DIR)/$(GUI_PACKAGE)/README.txt
	mkdir -p $(BUILD_DIR)/$(GUI_PACKAGE)/bin
	cp -r $(patsubst %, ${MINGW_DIR}/bin/%.dll, $(CORE_DLLS) $(GUI_DLLS)) $(ASSETS) $(BUILD_DIR)/$(BINARY)-gui.exe $(BUILD_DIR)/$(GUI_PACKAGE)/bin
	mkdir -p $(BUILD_DIR)/$(GUI_PACKAGE)/lib/gdk-pixbuf-2.0/2.10.0
	cp -r ${MINGW_DIR}/lib/gdk-pixbuf-2.0/2.10.0/loaders ${MINGW_DIR}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache $(BUILD_DIR)/$(GUI_PACKAGE)/lib/gdk-pixbuf-2.0/2.10.0
	mkdir -p $(BUILD_DIR)/$(GUI_PACKAGE)/share/icons
	cp -r ${MINGW_DIR}/share/icons/Adwaita $(BUILD_DIR)/$(GUI_PACKAGE)/share/icons
	7z a -r $@ ./$(BUILD_DIR)/$(GUI_PACKAGE)
	$(RM) -f -r $(BUILD_DIR)/$(GUI_PACKAGE)

$(BUILD_DIR)/$(TUI_PACKAGE).zip: $(BUILD_DIR)/$(BINARY)-tui $(DOCS)
	mkdir -p $(BUILD_DIR)/$(TUI_PACKAGE)
	cp ICON-LICENSE $(BUILD_DIR)/$(TUI_PACKAGE)/ICON-LICENSE.txt
	cp LICENSE $(BUILD_DIR)/$(TUI_PACKAGE)/LICENSE.txt
	cp NEWS $(BUILD_DIR)/$(TUI_PACKAGE)/NEWS.txt
	cp README $(BUILD_DIR)/$(TUI_PACKAGE)/README.txt
	mkdir -p $(BUILD_DIR)/$(TUI_PACKAGE)/bin
	cp -r $(patsubst %, ${MINGW_DIR}/bin/%.dll, $(CORE_DLLS)) $(BUILD_DIR)/$(BINARY)-tui.exe $(BUILD_DIR)/$(TUI_PACKAGE)/bin
	7z a -r $@ ./$(BUILD_DIR)/$(TUI_PACKAGE)
	$(RM) -f -r $(BUILD_DIR)/$(TUI_PACKAGE)

.PHONY: all debug clean cppcheck dist dist-windows-gui dist-windows-installer dist-windows-tui gui todo tui
