# Portal panel firmware — build and USB deploy
#
#   make              # build only
#   make deploy       # build + flash over USB (picotool)
#
# Options (also via repo-root .env — see .env.example):
#   make deploy PANEL_ID=0
#   make deploy NETWORK=dhcp
#   make deploy IP=10.1.1.10 GATEWAY=10.1.1.1
#   make deploy WS2812_PIN=26 WS2812_PIN1=27
#
# Environment:
#   PICO_SDK_PATH     default: ~/pico-sdk (fallback ~/pico/pico-sdk)

MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
-include $(MAKEFILE_DIR)../.env
-include $(MAKEFILE_DIR).env

ifeq ($(origin PICO_SDK_PATH), undefined)
  ifneq ($(wildcard $(HOME)/pico-sdk/pico_sdk_init.cmake),)
    PICO_SDK_PATH := $(HOME)/pico-sdk
  else
    PICO_SDK_PATH := $(HOME)/pico/pico-sdk
  endif
endif

BUILD_DIR     := build
UF2           := $(BUILD_DIR)/panel.uf2
CMAKE_STAMP   := $(BUILD_DIR)/.cmake_stamp
JOBS          ?= $(shell nproc 2>/dev/null || echo 4)
SERIAL_PORT   ?= $(shell ls /dev/ttyACM* 2>/dev/null | head -1)
ifeq ($(SERIAL_PORT),)
SERIAL_PORT   := /dev/ttyACM0
endif
SERIAL_BAUD   ?= 115200
NETWORK       ?= static

comma := ,
dot_to_csv = $(subst .,$(comma),$(1))

CMAKE_ARGS :=
ifdef PANEL_ID
CMAKE_ARGS += -DPANEL_ID_BUILD=$(PANEL_ID)
endif
ifdef WS2812_PIN
CMAKE_ARGS += -DWS2812_PIN_BUILD=$(WS2812_PIN)
endif
ifdef WS2812_PIN1
CMAKE_ARGS += -DWS2812_PIN1_BUILD=$(WS2812_PIN1)
endif
ifdef IP
CMAKE_ARGS += -DSTATIC_IP_BUILD=$(call dot_to_csv,$(IP))
endif
ifdef NETMASK
CMAKE_ARGS += -DSTATIC_SN_BUILD=$(call dot_to_csv,$(NETMASK))
endif
ifdef GATEWAY
CMAKE_ARGS += -DSTATIC_GW_BUILD=$(call dot_to_csv,$(GATEWAY))
endif
ifdef DNS
CMAKE_ARGS += -DSTATIC_DNS_BUILD=$(call dot_to_csv,$(DNS))
endif
ifeq ($(NETWORK),dhcp)
CMAKE_ARGS += -DPORTAL_USE_DHCP=ON
else ifeq ($(NO_DHCP),0)
CMAKE_ARGS += -DPORTAL_USE_DHCP=ON
else
CMAKE_ARGS += -DPORTAL_USE_DHCP=OFF
endif

CMAKE_STAMP_BODY := $(strip $(CMAKE_ARGS))

.PHONY: all build configure reconfigure deploy flash upload reset monitor clean help

all: build

help:
	@echo "Targets:"
	@echo "  make build      Build panel.uf2"
	@echo "  make deploy     Build and flash over USB"
	@echo "  make reset      USB reboot Pico"
	@echo "  make monitor    USB serial console"
	@echo "  make clean      Remove build directory"

build: configure
	@echo "==> Building panel firmware"
	# Host GCC 15 needs cstdint for pico-sdk pioasm
	CXXFLAGS='-include cstdint' PICO_SDK_PATH="$(PICO_SDK_PATH)" cmake --build $(BUILD_DIR) -j$(JOBS)
	@test -f "$(UF2)" || (echo "Error: build did not produce panel.uf2" && exit 1)
	@echo "==> Build OK: $(UF2)"

configure:
	@test -d "$(PICO_SDK_PATH)" || (echo "Error: pico-sdk not found at $(PICO_SDK_PATH)" && exit 1)
	@command -v cmake >/dev/null || (echo "Error: cmake is required" && exit 1)
	@mkdir -p $(BUILD_DIR)
	@STAMP='$(CMAKE_STAMP_BODY)'; \
	if [ ! -f "$(BUILD_DIR)/CMakeCache.txt" ] || [ ! -f "$(CMAKE_STAMP)" ] || [ "$$(cat $(CMAKE_STAMP))" != "$$STAMP" ]; then \
		echo "==> Configuring cmake in $(BUILD_DIR) $(CMAKE_ARGS)"; \
		CXXFLAGS='-include cstdint' PICO_SDK_PATH="$(PICO_SDK_PATH)" cmake -S . -B $(BUILD_DIR) $(CMAKE_ARGS); \
		echo "$$STAMP" > "$(CMAKE_STAMP)"; \
	fi

reconfigure:
	@mkdir -p $(BUILD_DIR)
	CXXFLAGS='-include cstdint' PICO_SDK_PATH="$(PICO_SDK_PATH)" cmake -S . -B $(BUILD_DIR) $(CMAKE_ARGS)
	@echo '$(CMAKE_STAMP_BODY)' > $(CMAKE_STAMP)

deploy: build
	@command -v picotool >/dev/null || { echo "Error: picotool not found"; exit 1; }
	@echo "==> Uploading $(UF2) over USB"
	@picotool load -x -f "$(UF2)"

flash: deploy
upload: deploy

reset:
	@command -v picotool >/dev/null || { echo "Error: picotool not found"; exit 1; }
	@picotool reboot -f
	@i=0; last=; \
	while [ $$i -lt 50 ]; do \
		cur=$$(ls /dev/ttyACM* 2>/dev/null | head -1); \
		if [ -n "$$cur" ] && [ "$$cur" = "$$last" ]; then \
			sleep 0.5; \
			if [ -e "$$cur" ]; then echo "==> Ready ($$cur)"; exit 0; fi; \
		fi; \
		last=$$cur; \
		i=$$((i + 1)); sleep 0.2; \
	done; \
	echo "==> Warning: serial not ready yet"; exit 0

monitor:
	@command -v picocom >/dev/null || { echo "Error: picocom not found"; exit 1; }
	@SERIAL=; i=0; \
	while [ $$i -lt 40 ]; do \
		for d in $(SERIAL_PORT) $$(ls /dev/ttyACM* 2>/dev/null); do \
			[ -n "$$d" ] && [ -e "$$d" ] || continue; \
			SERIAL=$$d; break; \
		done; \
		[ -n "$$SERIAL" ] && [ -e "$$SERIAL" ] && break; \
		i=$$((i + 1)); sleep 0.25; \
	done; \
	if [ -z "$$SERIAL" ] || [ ! -e "$$SERIAL" ]; then echo "Error: no serial port"; exit 1; fi; \
	echo "==> monitor $$SERIAL"; \
	exec picocom --baud $(SERIAL_BAUD) --flow n --echo --noreset "$$SERIAL"

clean:
	rm -rf $(BUILD_DIR)
