cmake_minimum_required(VERSION 3.16)

project(witcher001 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

option(STEAMSDK "Enable Steamworks SDK integration" OFF)

# ===========================================
# Поиск системных зависимостей Linux
# ===========================================
find_package(PkgConfig REQUIRED)
find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
find_package(Boost REQUIRED)
find_package(Freetype REQUIRED)

# Eigen3 ищется через свой конфиг, который ставится вместе с пакетом libeigen3-dev
find_package(Eigen3 REQUIRED NO_MODULE)

pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(SDL2_TTF REQUIRED SDL2_ttf)
pkg_check_modules(SDL2_MIXER REQUIRED SDL2_mixer)
pkg_check_modules(LIBZIP REQUIRED libzip)
# Имя пакета Lua может варьироваться (lua5.4, lua-5.4 или lua). Здесь указан дефолтный для Ubuntu
pkg_check_modules(LUA REQUIRED lua5.4)

include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/FetchDependenciesLinux.cmake")


# ===========================================
# sol2 (3.3.0) - header-only C++ bindings for Lua
# ===========================================

set(THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../thirdparty")

set(SOL2_SRC_DIR "${THIRDPARTY_DIR}/sol2-3.3.0")

# Apply patch for Clang/Emscripten compatibility in optional<T&>::emplace().
# The sentinel file prevents re-applying on subsequent cmake runs.
set(_sol2_sentinel "${SOL2_SRC_DIR}/.patched")
if(NOT EXISTS "${_sol2_sentinel}")
    find_package(Git QUIET)
    if(GIT_FOUND)
        execute_process(
            COMMAND ${GIT_EXECUTABLE} apply --ignore-whitespace
                "${CMAKE_CURRENT_LIST_DIR}/../cmake/patches/sol2-3.3.0-clang-optional.patch"
            WORKING_DIRECTORY "${SOL2_SRC_DIR}"
            RESULT_VARIABLE _sol2_patch_res
        )
        if(_sol2_patch_res EQUAL 0)
            file(WRITE "${_sol2_sentinel}" "patched\n")
            message(STATUS "Applied sol2 Clang optional patch")
        else()
            message(WARNING "sol2 patch failed (exit ${_sol2_patch_res}) — Clang/Emscripten builds may not compile")
        endif()
    else()
        message(WARNING "Git not found — cannot apply sol2 patch automatically. "
                        "Apply cmake/patches/sol2-3.3.0-clang-optional.patch manually.")
    endif()
endif()


# ===========================================
# Основной проект witcher001
# ===========================================
add_executable(witcher001
    ../src/main.cpp
    ../src/Game.cpp
    ../src/Game.h
    ../src/Character.cpp
    ../src/Character.h
    ../src/CharacterState.cpp
    ../src/CharacterState.h
    ../src/Environment.cpp
    ../src/Environment.h
    ../src/Localization.cpp
    ../src/Localization.h
    ../src/render/Renderer.cpp
    ../src/render/Renderer.h
    ../src/render/ShaderManager.cpp
    ../src/render/ShaderManager.h
    ../src/render/TextureManager.cpp
    ../src/render/TextureManager.h
    ../src/TextModel.cpp
    ../src/TextModel.h
    ../src/AudioPlayerAsync.cpp
    ../src/AudioPlayerAsync.h
    ../src/BoneAnimatedModelNew.cpp
    ../src/BoneAnimatedModelNew.h
    ../src/render/OpenGlExtensions.cpp
    ../src/render/OpenGlExtensions.h
    ../src/utils/Utils.cpp
    ../src/utils/Utils.h
    ../src/SparkEmitter.cpp
    ../src/SparkEmitter.h
    ../src/TeleportZone.h
    ../src/TeleportZone.cpp
    ../src/utils/TaskManager.cpp
    ../src/utils/TaskManager.h
    ../src/render/FrameBuffer.cpp
    ../src/render/FrameBuffer.h
    ../src/render/ShadowMap.cpp
    ../src/render/ShadowMap.h
    ../src/UiManager.cpp
    ../src/UiManager.h
    ../src/render/TextRenderer.h
    ../src/render/TextRenderer.cpp
    ../src/MenuManager.h
    ../src/MenuManager.cpp
    ../src/Location.h
    ../src/Location.cpp
    ../src/LocationState.h
    ../src/LocationState.cpp
    ../src/LocationEditor.h
    ../src/LocationEditor.cpp
    ../src/NpcCar.h
    ../src/NpcCar.cpp
    ../src/GameConstants.h
    ../src/GameConstants.cpp
    ../src/GameState.h
    ../src/GameState.cpp
    ../src/ScriptEngine.h
    ../src/ScriptEngine.cpp
    ../src/navigation/PathFinder.h
    ../src/navigation/PathFinder.cpp
    ../src/items/GameObjectLoader.h
    ../src/items/GameObjectLoader.cpp
    ../src/items/Item.h
    ../src/items/Item.cpp
    ../src/items/ItemRegistry.h
    ../src/items/ItemRegistry.cpp
    ../src/items/InteractiveObject.h
    ../src/items/InteractiveObject.cpp
    ../src/items/InteractiveObjectState.h
    ../src/dialogue/DialogueTypes.h
    ../src/dialogue/DialogueDatabase.h
    ../src/dialogue/DialogueDatabase.cpp
    ../src/dialogue/DialogueRuntime.h
    ../src/dialogue/DialogueRuntime.cpp
    ../src/dialogue/DialogueOverlay.h
    ../src/dialogue/DialogueOverlay.cpp
    ../src/dialogue/DialogueSystem.h
    ../src/dialogue/DialogueSystem.cpp
    ../src/dialogue/TranslationDatabase.h
    ../src/dialogue/TranslationDatabase.cpp
    ../src/quest/QuestTypes.h
    ../src/quest/QuestJournal.h
    ../src/quest/QuestJournal.cpp
    ../src/cutscene/CutsceneTypes.h
    ../src/cutscene/CutsceneDatabase.h
    ../src/cutscene/CutsceneDatabase.cpp
    ../src/cutscene/CutsceneRuntime.h
    ../src/cutscene/CutsceneRuntime.cpp
    ../src/cutscene/CutsceneOverlay.h
    ../src/cutscene/CutsceneOverlay.cpp
    ../src/render/UiQuad.h
)

# include-пути проекта
target_include_directories(witcher001 PRIVATE
    "${CMAKE_CURRENT_SOURCE_DIR}/../src"
    ${SDL2_INCLUDE_DIRS}
    ${SDL2_TTF_INCLUDE_DIRS}
    ${SDL2_MIXER_INCLUDE_DIRS}
    ${LIBZIP_INCLUDE_DIRS}
    ${LUA_INCLUDE_DIRS}
    ${EIGEN3_INCLUDE_DIRS}
    # sol2 - header-only, берем напрямую из thirdparty
    "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/sol2-3.3.0/include"
)

# Убираем WIN32_LEAN_AND_MEAN
target_compile_definitions(witcher001 PRIVATE
    PNG_ENABLED
    SDL_MAIN_HANDLED
)

# Линковка директорий для pkg-config (если пакеты не в /usr/lib)
target_link_directories(witcher001 PRIVATE
    ${SDL2_LIBRARY_DIRS}
    ${SDL2_TTF_LIBRARY_DIRS}
    ${SDL2_MIXER_LIBRARY_DIRS}
    ${LIBZIP_LIBRARY_DIRS}
    ${LUA_LIBRARY_DIRS}
)

# Линковка библиотек
target_link_libraries(witcher001 PRIVATE
    OpenGL::GL
    OpenGL::GLU
    ZLIB::ZLIB
    PNG::PNG
    Boost::boost
    Freetype::Freetype
    ${SDL2_LIBRARIES}
    ${SDL2_TTF_LIBRARIES}
    ${SDL2_MIXER_LIBRARIES}
    ${LIBZIP_LIBRARIES}
    ${LUA_LIBRARIES}
    pthread
)

# ===========================================
# Интеграция Steamworks SDK (если STEAMSDK=ON)
# ===========================================
if(STEAMSDK)
    message(STATUS "Steamworks SDK integration is ENABLED.")
    
    target_compile_definitions(witcher001 PRIVATE STEAMSDK)

    set(STEAM_SDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/steamworks_sdk_164/sdk")

    target_include_directories(witcher001 PRIVATE
        "${STEAM_SDK_DIR}/public"
        "${STEAM_SDK_DIR}/public/steam"
    )

    set(STEAM_LIB_DIR "${STEAM_SDK_DIR}/redistributable_bin/linux64")
    set(STEAM_LIB_NAME "steam_api")
    set(STEAM_SO_NAME "libsteam_api.so")

    find_library(STEAM_LIBRARY
        NAMES ${STEAM_LIB_NAME}
        PATHS ${STEAM_LIB_DIR}
        NO_DEFAULT_PATH
    )

    if(STEAM_LIBRARY)
        target_link_libraries(witcher001 PRIVATE ${STEAM_LIBRARY})
        message(STATUS "Found Steam API library: ${STEAM_LIBRARY}")
    else()
        message(FATAL_ERROR "Steam API library (${STEAM_LIB_NAME}) NOT found in ${STEAM_LIB_DIR}!")
    endif()

    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt" "4945840")
else()
    message(STATUS "Steamworks SDK integration is DISABLED.")
endif()

# ===========================================
# Настройка RPATH и копирование динамических библиотек
# ===========================================

# Указываем линкеру искать .so файлы в той же папке, где лежит бинарник ($ORIGIN)
set_target_properties(witcher001 PROPERTIES
    INSTALL_RPATH "$ORIGIN"
    BUILD_WITH_INSTALL_RPATH TRUE
)

# Поиск директорий, где лежат библиотеки
get_filename_component(LUA_SO_DIR ${LUA_SO_PATH} DIRECTORY)
get_filename_component(LIBZIP_SO_DIR ${LIBZIP_SO_PATH} DIRECTORY)

add_custom_command(TARGET witcher001 POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E echo "Copying shared libraries with sonames..."
    # Копируем библиотеки и все их симлинки (cp -P сохраняет структуру симлинков)
    COMMAND sh -c "cp -P ${LUA_SO_DIR}/liblua5.4.so* '$<TARGET_FILE_DIR:witcher001>/'"
    COMMAND sh -c "cp -P ${LIBZIP_SO_DIR}/libzip.so* '$<TARGET_FILE_DIR:witcher001>/'"
)

# Если включен Steam, копируем libsteam_api.so и steam_appid.txt
if(STEAMSDK)
    add_custom_command(TARGET witcher001 POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E echo "Copying Steam SDK components..."
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${STEAM_LIB_DIR}/${STEAM_SO_NAME}"
            "$<TARGET_FILE_DIR:witcher001>/${STEAM_SO_NAME}"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
            "$<TARGET_FILE_DIR:witcher001>/steam_appid.txt"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
            "${CMAKE_BINARY_DIR}/steam_appid.txt"
    )
endif()

# ===========================================
# Копирование ресурсов после сборки
# ===========================================
set(RUNTIME_RESOURCE_DIRS
    "resources"
    "audio"
)

foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
    add_custom_command(TARGET witcher001 POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to binary dir..."
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${CMAKE_SOURCE_DIR}/../${resdir}"
            "${CMAKE_BINARY_DIR}/${resdir}"
    )
endforeach()