# picosky - common development tasks. Source lives in src/ (src/*.lua modules +
# src/cart.p8, which #includes them and holds the gfx/label/sfx/music data). The
# root picosky.p8 / picosky*.js are BUILD OUTPUT, generated by `make build`.
# `make` or `make help` lists targets. Override any variable on the command line,
# e.g. `make build PICO8=/usr/bin/pico8` or `make serve PORT=9000`.

# --- config ------------------------------------------------------------------
PICO8        ?= $(HOME)/.local/pico-8/pico8
P8HOME       ?= /tmp/p8home
SHRINKO8     ?= python3 tools/shrinko8/shrinko8.py
# Tokens are picosky's binding budget (~90%); chars (~30%) and compressed (~55%)
# have headroom. --focus-tokens trades a little compressed size for ~140 fewer
# tokens per cart, so the .p8/.js outputs (and `count`) use it. The .p8.png
# targets stay on the default (compressed-focused) minify - their limit is the
# compressed ROM size, not tokens.
MINIFY       ?= --minify --focus-tokens
# CART = source cart (#includes src/*.lua + holds the gfx/sfx/music data).
# OUT  = built standalone demo cart (BUILD OUTPUT). Inline `#` comments are kept
# verbatim in Make values, so these are on their own lines (CART/OUT are file
# prerequisites below - trailing whitespace would break the rules).
CART         ?= src/cart.p8
SRC          := $(wildcard src/*.lua)
OUT          ?= picosky.p8
EXPORT       ?= picosky.js
DEMO_EXPORT  ?= picosky-demo.js
ZIP          ?= /tmp/pico8.zip
PORT         ?= 8080
HEADLESS_ENV  = SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy

.DEFAULT_GOAL := help

# --- help --------------------------------------------------------------------
.PHONY: help
help: ## Show this help
	@grep -E '^[a-zA-Z0-9_-]+:.*?## ' $(MAKEFILE_LIST) \
	  | awk 'BEGIN{FS=":.*?## "}{printf "  \033[36m%-14s\033[0m %s\n",$$1,$$2}'

# --- dev loop ----------------------------------------------------------------
.PHONY: serve
serve: ## Static dev server on 127.0.0.1:8080 (LAN=1 to expose on network, HOST= to pick interface)
	PORT=$(PORT) node serve.js $(if $(LAN),--lan,) $(if $(HOST),--host=$(HOST),)

# --- cart build --------------------------------------------------------------
# Source is src/cart.p8 (#includes src/*.lua + the gfx/sfx/music data). Two web
# carts come from it: shrinko8 minifies and sets the per-cart ONLINE flag (online
# = real client; demo = self-contained lua mock feed, no js data bridge), then
# headless PICO-8 exports each to JS. The root picosky.p8 is BUILD OUTPUT too -
# the minified standalone demo cart (online can't run without the js bridge).
$(OUT): $(CART) $(SRC)
	$(SHRINKO8) $(CART) $(OUT) $(MINIFY) --const ONLINE false
	@echo "built $(OUT) (standalone demo cart)"

$(EXPORT): $(CART) $(SRC)
	@mkdir -p build $(P8HOME)
	$(SHRINKO8) $(CART) build/online.p8 $(MINIFY) --const ONLINE true
	cd build && $(HEADLESS_ENV) $(PICO8) -home $(P8HOME) online.p8 -export "picosky.html"
	cp build/$(EXPORT) $(EXPORT)
	@echo "built $(EXPORT) (online)"

$(DEMO_EXPORT): $(CART) $(SRC)
	@mkdir -p build $(P8HOME)
	$(SHRINKO8) $(CART) build/demo.p8 $(MINIFY) --const ONLINE false
	cd build && $(HEADLESS_ENV) $(PICO8) -home $(P8HOME) demo.p8 -export "picosky-demo.html"
	cp build/$(DEMO_EXPORT) $(DEMO_EXPORT)
	@echo "built $(DEMO_EXPORT) (demo)"

.PHONY: build build-online build-demo cart
cart: $(OUT) ## Build the standalone demo cart -> picosky.p8
build-online: $(EXPORT) ## Export the online cart -> picosky.js
build-demo: $(DEMO_EXPORT) ## Export the demo cart -> picosky-demo.js
build: $(OUT) build-online build-demo ## Build root cart + export both web carts

# --- asset generation --------------------------------------------------------
.PHONY: avatars
avatars: ## Re-fetch + bake real Bluesky avatars into __gfx__
	node tools/fetch-avatars.js
	python3 tools/bake-avatars.py

.PHONY: images
images: ## Convert fox + npmx source images to PICO-8 hex strings (paste output into actions.lua)
	@echo "fox_hex:"; .venv/bin/python3 tools/gen-image.py tools/fox-reference.png
	@echo "npmx_hex:"; .venv/bin/python3 tools/gen-image.py tools/npmx-logo.png

.PHONY: icons
icons: ## Inject stats (reply/repost/heart 8-10) + footer (compose/refresh/quote 12-14) icons into __gfx__
	python3 tools/gen_icons.py $(CART)

.PHONY: label
label: ## Regenerate the cart __label__ from its butterfly sprite
	python3 tools/gen_label.py $(CART)

.PHONY: web-icons
web-icons: ## Regenerate favicons, app icons + Open Graph card from the page logo
	python3 tools/gen_web_icons.py

# --- .p8.png exports (BBS / Splore) ------------------------------------------
.PHONY: png
png: ## Build picosky.p8.png (demo+online, compressed ≤ 100%)
	$(SHRINKO8) $(CART) picosky.p8.png -f png --minify --title "A BLUESKY CLIENT FOR PICO-8" --title "made by vinnymac ♥"

.PHONY: png-online
png-online: ## Build picosky-online.p8.png (ONLINE=true, strips demo block)
	$(SHRINKO8) $(CART) picosky-online.p8.png -f png --minify --const ONLINE true

# --- code checks (shrinko8) --------------------------------------------------
# Lint runs on the readable source (the only place its warnings are meaningful);
# count runs on the minified per-cart builds - the budgets that actually ship.
.PHONY: lint
lint: ## Lint the cart source
	$(SHRINKO8) $(CART) --lint

.PHONY: count
count: ## Token / char / compressed budgets of the shipped carts (online + demo)
	@mkdir -p build
	@echo "online:"; $(SHRINKO8) $(CART) build/online-count.p8 $(MINIFY) --const ONLINE true --count
	@echo "demo:";   $(SHRINKO8) $(CART) build/demo-count.p8 $(MINIFY) --const ONLINE false --count

.PHONY: validate
validate: lint count ## Lint source + budget-check the shipped carts (the gate)

# --- deploy ------------------------------------------------------------------
DIST ?= dist

.PHONY: dist
dist: build ## Assemble web-only files into dist/ for Cloudflare Pages deploy
	rm -rf $(DIST)
	mkdir -p $(DIST)
	cp index.html sw.js manifest.webmanifest crt.js og.png $(DIST)/
	cp picosky.js picosky-demo.js picosky-comms.js picosky-firehose.js picosky-shim.js $(DIST)/
	cp client-metadata.json $(DIST)/
	cp -r favicons fonts vendor $(DIST)/
	@[ -f _headers ] && cp _headers $(DIST)/ || true

.PHONY: deploy
deploy: dist ## Build + deploy to Cloudflare Pages (requires wrangler auth)
	npx wrangler pages deploy $(DIST) --project-name picosky --commit-dirty=true

.PHONY: ci-dist
ci-dist: ## Assemble dist/ from committed artifacts (no pico8/python3 required)
	rm -rf $(DIST)
	mkdir -p $(DIST)
	cp index.html sw.js manifest.webmanifest crt.js og.png $(DIST)/
	cp picosky.js picosky-demo.js picosky-comms.js picosky-firehose.js picosky-shim.js $(DIST)/
	cp client-metadata.json $(DIST)/
	cp -r favicons fonts vendor $(DIST)/
	@[ -f _headers ] && cp _headers $(DIST)/ || true

.PHONY: ci-deploy
ci-deploy: ci-dist ## Deploy committed artifacts to Cloudflare Pages (CI-safe, no pico8 needed)
	CLOUDFLARE_ACCOUNT_ID=ebbd354a5e5728e183b95c92fbcfb770 npx wrangler pages deploy $(DIST) --project-name picosky --branch=main --commit-dirty=true

# --- setup / housekeeping ----------------------------------------------------
.PHONY: install-pico8
install-pico8: ## Install PICO-8 from /tmp/pico8.zip (override ZIP=)
	@test -f $(ZIP) || { echo "missing $(ZIP) (set ZIP=path)"; exit 1; }
	mkdir -p $(HOME)/.local/pico-8 $(HOME)/.local/bin /tmp/pico-8-extract
	unzip -o -q $(ZIP) -d /tmp/pico-8-extract
	cp -f /tmp/pico-8-extract/pico-8/pico8 /tmp/pico-8-extract/pico-8/pico8.dat $(HOME)/.local/pico-8/
	chmod +x $(HOME)/.local/pico-8/pico8
	ln -sf $(HOME)/.local/pico-8/pico8 $(HOME)/.local/bin/pico8
	@echo "installed: $(PICO8)"

.PHONY: setup
setup: ## Clone shrinko8 into tools/ (needed for lint/count/validate/build)
	git clone --depth=1 https://github.com/thisismypassport/shrinko8.git tools/shrinko8

.PHONY: clean
clean: ## Remove generated exports + build/ intermediates (keeps the built picosky.p8)
	rm -rf build picosky.js picosky.html picosky-demo.js picosky-demo.html picosky.p8.png picosky-online.p8.png
