cmake_minimum_required(VERSION 3.22)
project(MarisaFFI VERSION "0.3.1" LANGUAGES C CXX)

# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Options
option(ENABLE_NATIVE_CODE "Enable -march=native and supported instructions" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)

# Include directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libmarisa/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libmarisa/lib)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# Collect all marisa source files
set(MARISA_SOURCES
    libmarisa/lib/marisa/agent.cc
    libmarisa/lib/marisa/grimoire/io/mapper.cc
    libmarisa/lib/marisa/grimoire/io/reader.cc
    libmarisa/lib/marisa/grimoire/io/writer.cc
    libmarisa/lib/marisa/grimoire/trie/louds-trie.cc
    libmarisa/lib/marisa/grimoire/trie/tail.cc
    libmarisa/lib/marisa/grimoire/vector/bit-vector.cc
    libmarisa/lib/marisa/keyset.cc
    libmarisa/lib/marisa/trie.cc
)

# Collect all marisa header files
set(MARISA_HEADERS
    libmarisa/include/marisa.h
    libmarisa/include/marisa/agent.h
    libmarisa/include/marisa/base.h
    libmarisa/include/marisa/iostream.h
    libmarisa/include/marisa/key.h
    libmarisa/include/marisa/keyset.h
    libmarisa/include/marisa/query.h
    libmarisa/include/marisa/stdio.h
    libmarisa/include/marisa/trie.h
)

# Native code optimization
function(add_native_code TARGET)
    if(ENABLE_NATIVE_CODE)
        target_compile_options("${TARGET}" PRIVATE -march=native)
    endif()
endfunction()

# Create the core marisa library
add_library(marisa_core STATIC ${MARISA_SOURCES} ${MARISA_HEADERS})
target_include_directories(marisa_core PUBLIC 
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/libmarisa/include>
    $<INSTALL_INTERFACE:include>
)
add_native_code(marisa_core)

# Create the FFI wrapper library
if(BUILD_SHARED_LIBS)
    add_library(marisa_ffi SHARED marisa_ffi.cpp marisa_ffi.h)
else()
    add_library(marisa_ffi STATIC marisa_ffi.cpp marisa_ffi.h)
endif()
target_link_libraries(marisa_ffi PRIVATE marisa_core)
target_include_directories(marisa_ffi PUBLIC 
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:include>
)

# Set library properties
set_target_properties(marisa_ffi PROPERTIES
    VERSION "${MarisaFFI_VERSION}"
    SOVERSION "${MarisaFFI_VERSION_MAJOR}"
    OUTPUT_NAME "marisa_ffi"
)

# Export symbols for shared library
if(BUILD_SHARED_LIBS)
    target_compile_definitions(marisa_ffi PRIVATE MARISA_FFI_EXPORTS)
    set_target_properties(marisa_ffi PROPERTIES
        CXX_VISIBILITY_PRESET hidden
        VISIBILITY_INLINES_HIDDEN ON
    )
endif()

# Installation
install(TARGETS marisa_ffi marisa_core
    EXPORT MarisaFFITargets
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    RUNTIME DESTINATION bin
    INCLUDES DESTINATION include
)

install(FILES marisa_ffi.h DESTINATION include)

# Export targets for use by other projects
export(TARGETS marisa_ffi marisa_core
    FILE "${CMAKE_CURRENT_BINARY_DIR}/MarisaFFITargets.cmake"
)

# Create a simple test program
add_executable(marisa_ffi_test test.cpp)
target_link_libraries(marisa_ffi_test PRIVATE marisa_ffi marisa_core)

# Enable testing
enable_testing()
add_test(NAME marisa_ffi_test COMMAND marisa_ffi_test)
