# NOSTR Core Library Makefile
# Standalone library build system

CC = gcc
AR = ar
CFLAGS = -Wall -Wextra -std=c99 -fPIC -O2
DEBUG_CFLAGS = -Wall -Wextra -std=c99 -fPIC -g -DDEBUG
STATIC_CFLAGS = -Wall -Wextra -std=c99 -O2 -static

# Logging compile flags
LOGGING_FLAGS ?= -DENABLE_FILE_LOGGING -DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING
ifneq ($(ENABLE_LOGGING),)
    LOGGING_FLAGS += -DENABLE_FILE_LOGGING -DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING
endif

# Include paths
INCLUDES = -I. -Inostr_core -Icjson -Isecp256k1/include -Inostr_websocket -Imbedtls/include -Imbedtls/tf-psa-crypto/include -Imbedtls/tf-psa-crypto/drivers/builtin/include

# Library source files
LIB_SOURCES = nostr_core/core.c nostr_core/core_relays.c nostr_core/nostr_crypto.c nostr_core/nostr_secp256k1.c nostr_core/nostr_aes.c nostr_core/nostr_chacha20.c nostr_core/version.c nostr_websocket/nostr_websocket_mbedtls.c cjson/cJSON.c
LIB_OBJECTS = $(LIB_SOURCES:.c=.o)
ARM64_LIB_OBJECTS = $(LIB_SOURCES:.c=.arm64.o)

# secp256k1 library paths
SECP256K1_LIB = ./secp256k1/.libs/libsecp256k1.a
SECP256K1_PRECOMPUTED_LIB = ./secp256k1/.libs/libsecp256k1_precomputed.a

# ARM64 secp256k1 library paths
SECP256K1_ARM64_LIB = ./secp256k1/.libs/libsecp256k1_arm64.a
SECP256K1_ARM64_PRECOMPUTED_LIB = ./secp256k1/.libs/libsecp256k1_precomputed_arm64.a

# Library outputs (static only)
STATIC_LIB = libnostr_core.a
ARM64_STATIC_LIB = libnostr_core_arm64.a

# Example files
EXAMPLE_SOURCES = $(wildcard examples/*.c)
EXAMPLE_TARGETS = $(EXAMPLE_SOURCES:.c=)

# Default target - build both x64 and ARM64 static libraries
default: $(STATIC_LIB) $(ARM64_STATIC_LIB)

# Build all targets (static only)
all: $(STATIC_LIB) $(ARM64_STATIC_LIB) examples

# Static library - includes secp256k1 objects for self-contained library
$(STATIC_LIB): $(LIB_OBJECTS) $(SECP256K1_LIB)
	@echo "Creating self-contained static library: $@"
	@echo "Extracting secp256k1 objects..."
	@mkdir -p .tmp_secp256k1
	@cd .tmp_secp256k1 && $(AR) x ../$(SECP256K1_LIB)
	@if [ -f $(SECP256K1_PRECOMPUTED_LIB) ]; then \
		echo "Extracting secp256k1_precomputed objects..."; \
		cd .tmp_secp256k1 && $(AR) x ../$(SECP256K1_PRECOMPUTED_LIB); \
	fi
	@echo "Combining all objects into $@..."
	$(AR) rcs $@ $(LIB_OBJECTS) .tmp_secp256k1/*.o
	@rm -rf .tmp_secp256k1
	@echo "Self-contained static library created: $@"

# ARM64 cross-compilation settings
ARM64_CC = aarch64-linux-gnu-gcc
ARM64_AR = aarch64-linux-gnu-ar
ARM64_INCLUDES = -I. -Inostr_core -Icjson -Isecp256k1/include -Inostr_websocket -Imbedtls/include -Imbedtls/tf-psa-crypto/include -Imbedtls/tf-psa-crypto/drivers/builtin/include

# ARM64 static library - includes secp256k1 objects for self-contained library
$(ARM64_STATIC_LIB): $(ARM64_LIB_OBJECTS) $(SECP256K1_ARM64_LIB)
	@echo "Creating self-contained ARM64 static library: $@"
	@echo "Extracting ARM64 secp256k1 objects..."
	@mkdir -p .tmp_secp256k1_arm64
	@cd .tmp_secp256k1_arm64 && $(ARM64_AR) x ../$(SECP256K1_ARM64_LIB)
	@if [ -f $(SECP256K1_ARM64_PRECOMPUTED_LIB) ]; then \
		echo "Extracting ARM64 secp256k1_precomputed objects..."; \
		cd .tmp_secp256k1_arm64 && $(ARM64_AR) x ../$(SECP256K1_ARM64_PRECOMPUTED_LIB); \
	fi
	@echo "Combining all ARM64 objects into $@..."
	$(ARM64_AR) rcs $@ $(ARM64_LIB_OBJECTS) .tmp_secp256k1_arm64/*.o
	@rm -rf .tmp_secp256k1_arm64
	@echo "Self-contained ARM64 static library created: $@"

# Build secp256k1 for ARM64
$(SECP256K1_ARM64_LIB): secp256k1/configure
	@echo "Building secp256k1 for ARM64..."
	@echo "Cleaning secp256k1 source directory first..."
	@cd secp256k1 && make distclean 2>/dev/null || true
	@mkdir -p secp256k1/build_arm64
	@cd secp256k1/build_arm64 && \
		CC=$(ARM64_CC) AR=$(ARM64_AR) \
		../configure --host=aarch64-linux-gnu \
		--enable-module-schnorrsig \
		--enable-module-ecdh \
		--enable-experimental \
		--disable-shared \
		--enable-static \
		--with-pic \
		--prefix=$(PWD)/secp256k1/install_arm64 && \
		make -j$(shell nproc 2>/dev/null || echo 4)
	@mkdir -p secp256k1/.libs
	@cp secp256k1/build_arm64/.libs/libsecp256k1.a $(SECP256K1_ARM64_LIB)
	@if [ -f secp256k1/build_arm64/.libs/libsecp256k1_precomputed.a ]; then \
		cp secp256k1/build_arm64/.libs/libsecp256k1_precomputed.a $(SECP256K1_ARM64_PRECOMPUTED_LIB); \
	fi
	@echo "ARM64 secp256k1 libraries built successfully"
	@echo "Restoring x64 secp256k1 build..."
	@cd secp256k1 && ./configure --enable-module-schnorrsig --enable-module-ecdh --enable-experimental --disable-shared --enable-static --with-pic >/dev/null 2>&1 && make -j$(shell nproc 2>/dev/null || echo 4) >/dev/null 2>&1 || true

# Object files (x86_64)
%.o: %.c
	@echo "Compiling: $<"
	$(CC) $(CFLAGS) $(LOGGING_FLAGS) $(INCLUDES) -c $< -o $@

# ARM64 object files
%.arm64.o: %.c
	@echo "Compiling for ARM64: $<"
	$(ARM64_CC) $(CFLAGS) $(LOGGING_FLAGS) $(ARM64_INCLUDES) -c $< -o $@

# Examples
examples: $(EXAMPLE_TARGETS)

examples/%: examples/%.c $(STATIC_LIB)
	@echo "Building example: $@"
	$(CC) $(STATIC_CFLAGS) $(LOGGING_FLAGS) $(INCLUDES) $< -o $@ ./libnostr_core.a -lm

# Architecture-specific targets
x64: $(STATIC_LIB)
x64-only: $(STATIC_LIB)

# ARM64 targets
arm64: $(ARM64_STATIC_LIB)
arm64-all: $(ARM64_STATIC_LIB)
arm64-only: $(ARM64_STATIC_LIB)

# Debug build
debug: CFLAGS = $(DEBUG_CFLAGS)
debug: clean default

# Install library to system (static only)
install: $(STATIC_LIB)
	@echo "Installing static library..."
	sudo cp $(STATIC_LIB) /usr/local/lib/
	sudo cp nostr_core/nostr_core.h /usr/local/include/
	sudo cp nostr_core/nostr_crypto.h /usr/local/include/

# Uninstall library
uninstall:
	@echo "Uninstalling library..."
	sudo rm -f /usr/local/lib/$(STATIC_LIB)
	sudo rm -f /usr/local/include/nostr_core.h
	sudo rm -f /usr/local/include/nostr_crypto.h

# Test the library
test: examples/simple_keygen
	@echo "Running simple key generation test..."
	./examples/simple_keygen

# Run crypto tests
test-crypto:
	@echo "Running comprehensive crypto test suite..."
	cd tests && make test

# Clean build artifacts
clean:
	@echo "Cleaning build artifacts..."
	rm -f $(LIB_OBJECTS) $(ARM64_LIB_OBJECTS)
	rm -f $(STATIC_LIB) $(ARM64_STATIC_LIB)
	rm -f $(SECP256K1_ARM64_LIB) $(SECP256K1_ARM64_PRECOMPUTED_LIB)
	rm -f $(EXAMPLE_TARGETS)
	rm -rf .tmp_secp256k1 .tmp_secp256k1_arm64
	rm -rf secp256k1/build_arm64 secp256k1/install_arm64

# Create distribution package
dist: clean
	@echo "Creating distribution package..."
	mkdir -p dist/nostr_core
	cp -r *.h *.c Makefile examples/ tests/ README.md LICENSE dist/nostr_core/ 2>/dev/null || true
	cd dist && tar -czf nostr_core.tar.gz nostr_core/
	@echo "Distribution package created: dist/nostr_core.tar.gz"

# Help
help:
	@echo "NOSTR Core Library Build System"
	@echo "==============================="
	@echo ""
	@echo "Available targets:"
	@echo "  default      - Build both x64 and ARM64 static libraries (recommended)"
	@echo "  all          - Build both architectures and examples"
	@echo "  x64          - Build x64 static library only"
	@echo "  x64-only     - Build x64 static library only"
	@echo "  arm64        - Build ARM64 static library only"
	@echo "  arm64-only   - Build ARM64 static library only"
	@echo "  arm64-all    - Build ARM64 static library only"
	@echo "  debug        - Build with debug symbols (both architectures)"
	@echo "  examples     - Build example programs"
	@echo "  test         - Run simple test"
	@echo "  test-crypto  - Run comprehensive crypto test suite"
	@echo "  install      - Install static library to system (/usr/local)"
	@echo "  uninstall    - Remove library from system"
	@echo "  clean        - Remove build artifacts"
	@echo "  dist         - Create distribution package"
	@echo "  help         - Show this help"
	@echo ""
	@echo "Library outputs (static only, self-contained with secp256k1):"
	@echo "  $(STATIC_LIB)      - x86_64 static library"
	@echo "  $(ARM64_STATIC_LIB) - ARM64 static library"
	@echo ""
	@echo "Both libraries are self-contained and include secp256k1 objects."
	@echo "Users only need to link with the library + -lm (no secp256k1 dependency)."

.PHONY: default all x64 x64-only arm64 arm64-all arm64-only debug examples test test-crypto install uninstall clean dist help
