cmake_minimum_required(VERSION 3.28)
project(ENCRYPTED_CPP VERSION 1.0.0)

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# ========== 目录设置 ==========
# 项目根目录
set(PROJECT_ROOT "${CMAKE_SOURCE_DIR}")

# 源代码目录 - 使用cpp-src目录
if(EXISTS "${PROJECT_ROOT}/cpp-src")
    set(SOURCE_DIR "${PROJECT_ROOT}/cpp-src")
    set(HEADER_DIR "${PROJECT_ROOT}/cpp-src")
    message(STATUS "Using cpp-src directory: ${CPP_SRC_DIR}")
else()
    # 如果没有cpp-src目录，使用当前目录
    set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    set(HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    message(STATUS "Using current directory as source directory")
endif()

# ========== 手动设置Java路径 ==========
# 查找Java HOME
if(DEFINED ENV{JAVA_HOME})
    set(JAVA_HOME $ENV{JAVA_HOME})
    message(STATUS "Found JAVA_HOME: ${JAVA_HOME}")
else()
    # 尝试通过which或where命令查找java
    if(WIN32)
        execute_process(
                COMMAND where java
                OUTPUT_VARIABLE JAVA_PATH
                OUTPUT_STRIP_TRAILING_WHITESPACE
        )
    else()
        execute_process(
                COMMAND which java
                OUTPUT_VARIABLE JAVA_PATH
                OUTPUT_STRIP_TRAILING_WHITESPACE
        )
    endif()

    if(JAVA_PATH)
        # 从java路径推断JAVA_HOME
        get_filename_component(JAVA_HOME "${JAVA_PATH}" DIRECTORY)
        get_filename_component(JAVA_HOME "${JAVA_HOME}" DIRECTORY)
        message(STATUS "Inferred JAVA_HOME: ${JAVA_HOME}")
    else()
        message(WARNING "Java not found in PATH")
        set(JAVA_HOME "C:/Program Files/Java/jdk-21")  # Windows默认路径
    endif()
endif()

# 设置Java包含目录
set(JAVA_INCLUDE_DIRS
        "${JAVA_HOME}/include"
)

# 添加平台特定include目录
if(WIN32)
    list(APPEND JAVA_INCLUDE_DIRS "${JAVA_HOME}/include/win32")
elseif(APPLE)
    list(APPEND JAVA_INCLUDE_DIRS "${JAVA_HOME}/include/darwin")
else()
    list(APPEND JAVA_INCLUDE_DIRS "${JAVA_HOME}/include/linux")
endif()

# 验证Java包含目录是否存在
foreach(dir IN LISTS JAVA_INCLUDE_DIRS)
    if(NOT EXISTS "${dir}")
        message(WARNING "Java include directory not found: ${dir}")
    else()
        message(STATUS "Found Java include: ${dir}")
    endif()
endforeach()

# ========== 查找源文件和头文件 ==========
# 查找所有的C++源文件
file(GLOB SOURCE_FILES
        "${SOURCE_DIR}/*.cpp"
        "${SOURCE_DIR}/*.cxx"
)

if(NOT SOURCE_FILES)
    # 如果没找到，尝试递归查找
    file(GLOB_RECURSE SOURCE_FILES
            "${SOURCE_DIR}/*.cpp"
            "${SOURCE_DIR}/*.cxx"
            "${SOURCE_DIR}/*.cc"
    )
endif()

if(SOURCE_FILES)
    message(STATUS "Found source files:")
    foreach(file ${SOURCE_FILES})
        message(STATUS "  ${file}")
    endforeach()
else()
    message(FATAL_ERROR "No source files found in ${SOURCE_DIR}")
endif()

# 查找头文件
file(GLOB HEADER_FILES
        "${HEADER_DIR}/*.h"
        "${HEADER_DIR}/*.hpp"
)

# ========== 创建库目标 ==========
# 库名称
if(WIN32)
    set(LIBRARY_NAME "ClassEncrypt")
else()
    set(LIBRARY_NAME "ClassEncrypt")
endif()

# 添加库目标
add_library(${LIBRARY_NAME} SHARED ${SOURCE_FILES}
        "src/EnhancedEncryptionMagic.cpp"
        src/guard/JByteArrayGuard.cpp)

# 设置输出名称和位置
set_target_properties(${LIBRARY_NAME} PROPERTIES
        OUTPUT_NAME ${LIBRARY_NAME}
        DEBUG_POSTFIX "d"
)

# 设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

# ========== 包含目录 ==========
target_include_directories(${LIBRARY_NAME} PRIVATE
        ${JAVA_INCLUDE_DIRS}
        ${HEADER_DIR}
)

# ========== 编译选项 ==========
if(MSVC)
    target_compile_options(${LIBRARY_NAME} PRIVATE
            /W3           # 警告级别3
            /WX-          # 不将警告视为错误
            /EHsc         # C++异常处理
            $<$<CONFIG:Debug>:/MDd>    # 调试版本使用MDd
            $<$<CONFIG:Release>:/MD>   # 发布版本使用MD
            $<$<CONFIG:RelWithDebInfo>:/MD>
            $<$<CONFIG:MinSizeRel>:/MD>
    )

    # MSVC预处理器定义
    target_compile_definitions(${LIBRARY_NAME} PRIVATE
            _CRT_SECURE_NO_WARNINGS
            _WINSOCK_DEPRECATED_NO_WARNINGS
            BUILDING_DLL
            JNIEXPORT=__declspec(dllexport)
    )
else()
    target_compile_options(${LIBRARY_NAME} PRIVATE
            -Wall
            -Wextra
            -Wno-unused-parameter
            -fPIC
            $<$<CONFIG:Debug>:-g -O0>
            $<$<CONFIG:Release>:-O2>
            $<$<CONFIG:RelWithDebInfo>:-O2 -g>
            $<$<CONFIG:MinSizeRel>:-Os>
    )

    # GCC/Clang预处理器定义
    target_compile_definitions(${LIBRARY_NAME} PRIVATE
            BUILDING_DLL
    )

    if(APPLE)
        target_compile_options(${LIBRARY_NAME} PRIVATE
                -stdlib=libc++
        )
    endif()
endif()

# ========== 链接库 ==========
if(WIN32)
    # Windows链接库
    target_link_libraries(${LIBRARY_NAME} PRIVATE
            kernel32.lib
            user32.lib
            gdi32.lib
            winspool.lib
            shell32.lib
            ole32.lib
            oleaut32.lib
            uuid.lib
            comdlg32.lib
            advapi32.lib
    )
else()
    # Linux/macOS链接库
    target_link_libraries(${LIBRARY_NAME} PRIVATE
            pthread
            dl
    )

    if(APPLE)
        target_link_options(${LIBRARY_NAME} PRIVATE
                -undefined dynamic_lookup
        )
    endif()
endif()

# ========== 安装配置（可选） ==========
if(NOT DEFINED CMAKE_SKIP_INSTALL_RULES)
    install(TARGETS ${LIBRARY_NAME}
            LIBRARY DESTINATION lib
            RUNTIME DESTINATION bin
            ARCHIVE DESTINATION lib
    )

    # 安装头文件
    if(HEADER_FILES)
        install(FILES ${HEADER_FILES} DESTINATION include)
    endif()
endif()

# ========== 输出总结信息 ==========
message(STATUS "")
message(STATUS "=========================================")
message(STATUS "Project Configuration Summary")
message(STATUS "=========================================")
message(STATUS "Project: ${PROJECT_NAME}")
message(STATUS "Version: ${PROJECT_VERSION}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Source directory: ${SOURCE_DIR}")
message(STATUS "Header directory: ${HEADER_DIR}")
message(STATUS "Java include dirs: ${JAVA_INCLUDE_DIRS}")
message(STATUS "Target library: ${LIBRARY_NAME}")
message(STATUS "C++ standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "Output directory: ${CMAKE_BINARY_DIR}")
message(STATUS "=========================================")