CC ?= cc
AR ?= ar
CFLAGS ?= -std=c11 -O2 -Wall -Wextra -Iinclude -Isrc
LDFLAGS ?=
PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include
PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
VERSION ?= 0.0.1-preview

UNAME := $(shell uname)
ENABLE_OPENSSL_TLS ?= auto
TLS_CFLAGS =
TLS_LDFLAGS =
ifeq ($(UNAME), Linux)
  ifneq ($(ENABLE_OPENSSL_TLS), 0)
    HAVE_OPENSSL_TLS := $(shell pkg-config --exists openssl 2>/dev/null && echo 1)
    ifeq ($(HAVE_OPENSSL_TLS), 1)
      TLS_CFLAGS := -DLEDGERD_CLIENT_TLS_OPENSSL $(shell pkg-config --cflags openssl 2>/dev/null)
      TLS_LDFLAGS := $(shell pkg-config --libs openssl 2>/dev/null)
      $(info [build] C SDK TLS backend enabled (OpenSSL))
    else ifeq ($(ENABLE_OPENSSL_TLS), 1)
      TLS_CFLAGS := -DLEDGERD_CLIENT_TLS_OPENSSL
      TLS_LDFLAGS := -lssl -lcrypto
      $(info [build] C SDK TLS backend forced (OpenSSL))
    else
      $(info [build] OpenSSL not found via pkg-config; C SDK TLS backend disabled)
    endif
  endif
endif

CFLAGS += $(TLS_CFLAGS)
LDFLAGS += $(TLS_LDFLAGS)

LIB = build/libledgerd_client.a
OBJ = build/ledgerd_client.o
EXAMPLE = build/example_transfer
TEST_CODEC = build/test_sdk_codec
TEST_IO = build/test_io_timeout
TEST_RETRY = build/test_smart_retry
TEST_AMOUNT = build/test_amount
TEST_KINDS = build/test_buffered_kinds
PKGCONFIG = build/ledgerd_client.pc

.PHONY: all clean example install pkgconfig test test-io test-retry test-amount test-kinds FORCE

FORCE:

all: $(LIB)

build:
	mkdir -p build

$(OBJ): src/ledgerd_client.c src/ledgerd_protocol.h include/ledgerd/ledgerd_client.h | build
	$(CC) $(CFLAGS) -c $< -o $@

$(LIB): $(OBJ)
	$(AR) rcs $@ $^

# PC_PREFIX: the pkg-config prefix line. `make install` writes PREFIX; the
# release tarball uses a relocatable one ($${pcfiledir}/../..), so the unpacked
# tree works wherever it lands. The static library needs OpenSSL (when built
# with TLS) and pthreads at link time, so Libs names them.
PC_PREFIX ?= $(PREFIX)
PC_LIBDIR ?= $(LIBDIR)
PC_INCLUDEDIR ?= $(INCLUDEDIR)
$(PKGCONFIG): FORCE | build
	printf '%s\n' \
	  'prefix=$(PC_PREFIX)' \
	  'exec_prefix=$${prefix}' \
	  'libdir=$(PC_LIBDIR)' \
	  'includedir=$(PC_INCLUDEDIR)' \
	  '' \
	  'Name: ledgerd-client' \
	  'Description: TulaDB raw C SDK client' \
	  'Version: $(VERSION)' \
	  'Cflags: -I$${includedir}' \
	  'Libs: -L$${libdir} -lledgerd_client $(LDFLAGS) -lpthread' \
	  > $@

$(TEST_CODEC): tests/test_sdk_codec.c src/ledgerd_protocol.h include/ledgerd/ledgerd_client.h $(LIB)
	$(CC) $(CFLAGS) $< $(LIB) -o $@ $(LDFLAGS) -lpthread

# I/O timeout tests need a TLS-capable client on every platform (the library
# above enables TLS only on Linux), so they link their own object, built with
# OpenSSL whenever pkg-config finds it. Without OpenSSL the TLS cases skip.
IO_TLS := $(shell pkg-config --exists openssl 2>/dev/null && echo 1)
ifeq ($(IO_TLS), 1)
  IO_CFLAGS := -DLEDGERD_CLIENT_TLS_OPENSSL -DTEST_HAVE_TLS $(shell pkg-config --cflags openssl 2>/dev/null)
  IO_LDFLAGS := $(shell pkg-config --libs openssl 2>/dev/null)
endif
TEST_IO_OBJ = build/io/ledgerd_client.o

$(TEST_IO_OBJ): src/ledgerd_client.c src/ledgerd_protocol.h include/ledgerd/ledgerd_client.h | build
	mkdir -p build/io
	$(CC) $(CFLAGS) $(IO_CFLAGS) -c $< -o $@

$(TEST_IO): tests/test_io_timeout.c $(TEST_IO_OBJ)
	$(CC) $(CFLAGS) $(IO_CFLAGS) $< $(TEST_IO_OBJ) -o $@ $(LDFLAGS) $(IO_LDFLAGS) -lpthread

test-io: $(TEST_IO)
	./$(TEST_IO)

# The retry tests compile the library into the test (they include
# src/ledgerd_client.c) to swap its static sleep/clock hooks.
$(TEST_RETRY): tests/test_smart_retry.c src/ledgerd_client.c src/ledgerd_protocol.h include/ledgerd/ledgerd_client.h | build
	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -lpthread

test-retry: $(TEST_RETRY)
	./$(TEST_RETRY)

# Decimal amounts against the shared contracts/amount-vectors.json.
$(TEST_AMOUNT): tests/test_amount.c include/ledgerd/ledgerd_client.h $(LIB)
	$(CC) $(CFLAGS) $< $(LIB) -o $@ $(LDFLAGS) -lpthread

test-amount: $(TEST_AMOUNT)
	./$(TEST_AMOUNT)

# The buffered client batches every write kind (fake engine on loopback).
$(TEST_KINDS): tests/test_buffered_kinds.c src/ledgerd_protocol.h include/ledgerd/ledgerd_client.h $(LIB)
	$(CC) $(CFLAGS) $< $(LIB) -o $@ $(LDFLAGS) -lpthread

test-kinds: $(TEST_KINDS)
	./$(TEST_KINDS)

test: $(TEST_CODEC) $(TEST_IO) $(TEST_RETRY) $(TEST_AMOUNT) $(TEST_KINDS)
	./$(TEST_CODEC)
	./$(TEST_IO)
	./$(TEST_RETRY)
	./$(TEST_AMOUNT)
	./$(TEST_KINDS)

example: $(LIB) examples/example_transfer.c
	$(CC) $(CFLAGS) examples/example_transfer.c $(LIB) -o $(EXAMPLE) $(LDFLAGS)

install: $(LIB) $(PKGCONFIG)
	install -d $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR)/ledgerd $(DESTDIR)$(PKGCONFIGDIR)
	install -m 0644 $(LIB) $(DESTDIR)$(LIBDIR)/libledgerd_client.a
	install -m 0644 include/ledgerd/ledgerd_client.h $(DESTDIR)$(INCLUDEDIR)/ledgerd/ledgerd_client.h
	install -m 0644 $(PKGCONFIG) $(DESTDIR)$(PKGCONFIGDIR)/ledgerd_client.pc

pkgconfig: $(PKGCONFIG)

clean:
	rm -rf build
