# CMakeLists.txt for miniscript-sys
#
# This builds a static library that wraps Bitcoin Core's miniscript
# implementation with a C ABI for FFI consumption.

cmake_minimum_required(VERSION 3.16)
project(miniscript_wrapper VERSION 0.1.0 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Build type
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

# Options
option(BUILD_SHARED_LIBS "Build shared library" OFF)
option(MINISCRIPT_WRAPPER_TESTS "Build tests" OFF)

# Bitcoin Core source directory
set(BITCOIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/bitcoin/src"
    CACHE PATH "Path to Bitcoin Core src directory")

if(NOT EXISTS "${BITCOIN_SRC_DIR}/script/miniscript.h")
  message(FATAL_ERROR
        "Bitcoin Core source not found at ${BITCOIN_SRC_DIR}\n"
        "Please either:\n"
        "  1. Clone Bitcoin Core: git submodule add https://github.com/bitcoin/bitcoin vendor/bitcoin\n"
        "  2. Set BITCOIN_SRC_DIR to point to your Bitcoin Core src directory"
    )
endif()

# Find required dependencies (from Bitcoin Core's build)
find_package(Boost 1.73.0 REQUIRED)

# Include directories
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/cpp
    ${BITCOIN_SRC_DIR}
    ${BITCOIN_SRC_DIR}/..  # For config/bitcoin-config.h if needed
    ${Boost_INCLUDE_DIRS}
)

# Compile definitions to stub out what we don't need
add_compile_definitions(
    # Avoid pulling in full Bitcoin Core dependencies
    HAVE_CONFIG_H=0

    # We don't need the wallet
    ENABLE_WALLET=0

    # Minimal secp256k1 (we might not even need real crypto for string keys)
    SECP256K1_CONTEXT_NONE=1
)

# Bitcoin Core requires assertions to be enabled (cannot have NDEBUG defined)
# Remove NDEBUG from release flags
string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")

# Bitcoin Core sources we need for miniscript
# This is the minimal set required to compile miniscript
set(BITCOIN_CORE_SOURCES
    # Core miniscript
    ${BITCOIN_SRC_DIR}/script/miniscript.cpp

    # Script basics (miniscript depends on these)
    ${BITCOIN_SRC_DIR}/script/script.cpp

    # Script parsing (used by miniscript string parsing)
    ${BITCOIN_SRC_DIR}/script/parsing.cpp

    # Utility functions used by miniscript
    ${BITCOIN_SRC_DIR}/util/strencodings.cpp
    ${BITCOIN_SRC_DIR}/util/string.cpp

    # Span parsing (used by miniscript string parsing) - may not exist in newer versions
    ${BITCOIN_SRC_DIR}/util/spanparsing.cpp
)

# Check which sources actually exist (API changes between versions)
set(BITCOIN_SOURCES_FILTERED)
foreach(src ${BITCOIN_CORE_SOURCES})
  if(EXISTS ${src})
    list(APPEND BITCOIN_SOURCES_FILTERED ${src})
  else()
    message(WARNING "Bitcoin Core source not found: ${src}")
  endif()
endforeach()

# Our wrapper sources
set(WRAPPER_SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/cpp/miniscript_wrapper.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/cpp/stubs.cpp
)

# Create the library
add_library(miniscript_wrapper
    ${BITCOIN_SOURCES_FILTERED}
    ${WRAPPER_SOURCES}
)

# Suppress warnings from Bitcoin Core code (it's not our code to fix)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
  set_source_files_properties(
        ${BITCOIN_SOURCES_FILTERED}
        PROPERTIES COMPILE_FLAGS "-w"
    )

  # Our wrapper should have full warnings
  target_compile_options(miniscript_wrapper PRIVATE
        $<$<COMPILE_LANGUAGE:CXX>:-Wall -Wextra -Wpedantic>
    )
endif()

# Link libraries
target_link_libraries(miniscript_wrapper
    PRIVATE
        ${Boost_LIBRARIES}
)

# Install targets
install(TARGETS miniscript_wrapper
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
)

install(FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/cpp/miniscript_wrapper.h
    DESTINATION include
)

# Tests
if(MINISCRIPT_WRAPPER_TESTS)
  enable_testing()

  add_executable(test_wrapper
        ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_wrapper.cpp
    )
  target_link_libraries(test_wrapper miniscript_wrapper)

  add_test(NAME test_wrapper COMMAND test_wrapper)
endif()

# Print configuration summary
message(STATUS "")
message(STATUS "miniscript-wrapper configuration:")
message(STATUS "  Bitcoin Core source: ${BITCOIN_SRC_DIR}")
message(STATUS "  Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "  Shared libs: ${BUILD_SHARED_LIBS}")
message(STATUS "")
