cmake_minimum_required(VERSION 3.10)
project(t3lru LANGUAGES CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

include(GNUInstallDirs)

# Set C++ standard to match the main project
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Disable RTTI
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")

# Create the t3lru library
add_library(t3lru STATIC
    src/t3_lru_policy.cpp
)

# Common include directories
set(COMMON_INCLUDE_DIRS
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${CMAKE_CURRENT_SOURCE_DIR}/../..
)

include_directories(${COMMON_INCLUDE_DIRS})

# Find Threads package
find_package(Threads REQUIRED)

# Link t3lru library with Threads
target_link_libraries(t3lru
    Threads::Threads
)

# Set target properties
set_target_properties(t3lru
    PROPERTIES
    POSITION_INDEPENDENT_CODE ON
)

# Platform-specific linking
if(WIN32)
    target_link_libraries(t3lru c++)
else()
    target_link_libraries(t3lru stdc++)
endif()

# Install the library to build directory
install(TARGETS t3lru
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

# Install headers to build directory
install(DIRECTORY include/t3_lru/
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/t3_lru
    FILES_MATCHING PATTERN "*.hpp"
)

# Option to build tests
option(BUILD_TESTS "Build unit tests for t3lru" OFF)

if(BUILD_TESTS)
    # Enable testing
    enable_testing()

    # Find Google Test
    find_package(GTest)
    if(NOT GTest_FOUND)
        message(FATAL_ERROR "Google Test is required for building tests but was not found. Consider to disable tests with -DBUILD_TESTS=OFF")
    endif()

    # Common include directories for tests
    set(TEST_INCLUDE_DIRS
        ${COMMON_INCLUDE_DIRS}
        ${CMAKE_CURRENT_SOURCE_DIR}/test
        ${CMAKE_CURRENT_SOURCE_DIR}/../../extension/tests/cache
    )

    # Common libraries for tests
    set(TEST_LIBRARIES
        GTest::gtest
        GTest::gtest_main
        GTest::gmock
        GTest::gmock_main
        t3lru
    )

    # Platform-specific test libraries
    if(WIN32)
        list(APPEND TEST_LIBRARIES c++)
    else()
        list(APPEND TEST_LIBRARIES stdc++)
    endif()

    # Propagate BUILD_TESTS flag to production library so TestAccess guards are active
    target_compile_definitions(t3lru PUBLIC BUILD_TESTS=1)

    # Helper function to create test executables
    function(add_t3lru_test TEST_NAME TEST_FILE)
        add_executable(${TEST_NAME}
            ${CMAKE_CURRENT_SOURCE_DIR}/test/${TEST_FILE}
        )
        target_link_libraries(${TEST_NAME} PRIVATE ${TEST_LIBRARIES})
        target_include_directories(${TEST_NAME} PRIVATE ${TEST_INCLUDE_DIRS})
        set_target_properties(${TEST_NAME}
            PROPERTIES
            POSITION_INDEPENDENT_CODE ON
        )
        add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
    endfunction()

    # add_t3lru_test(t3_lru_policy_internal_test t3_lru_policy_internal_test.cpp)
    add_t3lru_test(handle_impl_test handle_impl_test.cpp)
    add_t3lru_test(halflife_test halflife_test.cpp)
    add_t3lru_test(timestamp_test timestamp_test.cpp)
    add_t3lru_test(segment_test segment_test.cpp)
    add_t3lru_test(tier_group_test tier_group_test.cpp)
    add_t3lru_test(tier_manager_test tier_manager_test.cpp)
    add_t3lru_test(tier_group_tls_buffer_test tier_group_tls_buffer_test.cpp)
    add_t3lru_test(integration_test integration_test.cpp)
    add_t3lru_test(segment_list_test segment_queue_test.cpp)

    # Create aggregate target for all tests
    add_custom_target(t3lru_tests)
    add_dependencies(t3lru_tests
        # t3_lru_policy_internal_test
        handle_impl_test
        halflife_test
        timestamp_test
        segment_test
        tier_group_test
        tier_manager_test
        tier_group_tls_buffer_test
        integration_test
        segment_list_test
    )
endif()
