cmake_minimum_required(VERSION 3.16)

project(space_game001 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# ==============================
# Папка для всех сторонних либ
# ==============================
set(THIRDPARTY_DIR "${CMAKE_SOURCE_DIR}/thirdparty1")
file(MAKE_DIRECTORY "${THIRDPARTY_DIR}")

macro(log msg)
    message(STATUS "${msg}")
endmacro()

# ===========================================
# 1) ZLIB (zlib131.zip → zlib-1.3.1)
# ===========================================
set(ZLIB_ARCHIVE      "${THIRDPARTY_DIR}/zlib131.zip")
set(ZLIB_SRC_DIR      "${THIRDPARTY_DIR}/zlib-1.3.1")
set(ZLIB_BUILD_DIR    "${ZLIB_SRC_DIR}/build")
set(ZLIB_INSTALL_DIR  "${ZLIB_SRC_DIR}/install")

if(NOT EXISTS "${ZLIB_ARCHIVE}")
    log("Downloading zlib131.zip ...")
    file(DOWNLOAD
        "https://www.zlib.net/zlib131.zip"
        "${ZLIB_ARCHIVE}"
        SHOW_PROGRESS
    )
endif()

if(NOT EXISTS "${ZLIB_SRC_DIR}/CMakeLists.txt")
    log("Extracting zlib131.zip to zlib-1.3.1 ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND} -E tar xvf "${ZLIB_ARCHIVE}"
        WORKING_DIRECTORY "${THIRDPARTY_DIR}"
        RESULT_VARIABLE _zlib_extract_res
    )
    if(NOT _zlib_extract_res EQUAL 0)
        message(FATAL_ERROR "Failed to extract zlib archive")
    endif()
endif()

file(MAKE_DIRECTORY "${ZLIB_BUILD_DIR}")

# проверяем, собран ли уже zlib
set(_have_zlib FALSE)
foreach(candidate
    "${ZLIB_INSTALL_DIR}/lib/zlibstatic.lib"
    "${ZLIB_INSTALL_DIR}/lib/zlib.lib"
    "${ZLIB_INSTALL_DIR}/lib/zlibd.lib"
    "${ZLIB_INSTALL_DIR}/lib/zlib1.lib"
)
    if(EXISTS "${candidate}")
        set(_have_zlib TRUE)
        break()
    endif()
endforeach()

if(NOT _have_zlib)
    log("Configuring zlib ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            -G "${CMAKE_GENERATOR}"
            -S "${ZLIB_SRC_DIR}"
            -B "${ZLIB_BUILD_DIR}"
            -DCMAKE_INSTALL_PREFIX=${ZLIB_INSTALL_DIR}
        RESULT_VARIABLE _zlib_cfg_res
    )
    if(NOT _zlib_cfg_res EQUAL 0)
        message(FATAL_ERROR "zlib configure failed")
    endif()

    log("Building zlib (Debug) ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            --build "${ZLIB_BUILD_DIR}" --config Debug
        RESULT_VARIABLE _zlib_build_res
    )
    if(NOT _zlib_build_res EQUAL 0)
        message(FATAL_ERROR "zlib build failed")
    endif()

    log("Installing zlib (Debug) ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            --install "${ZLIB_BUILD_DIR}" --config Debug
        RESULT_VARIABLE _zlib_inst_res
    )
    if(NOT _zlib_inst_res EQUAL 0)
        message(FATAL_ERROR "zlib install failed")
    endif()
endif()

set(ZLIB_LIB_FILE "")
foreach(candidate
    "${ZLIB_INSTALL_DIR}/lib/zlibstatic.lib"
    "${ZLIB_INSTALL_DIR}/lib/zlib.lib"
    "${ZLIB_INSTALL_DIR}/lib/zlibd.lib"
    "${ZLIB_INSTALL_DIR}/lib/zlib1.lib"
)
    if(EXISTS "${candidate}")
        set(ZLIB_LIB_FILE "${candidate}")
        break()
    endif()
endforeach()
if(ZLIB_LIB_FILE STREQUAL "")
    message(FATAL_ERROR "Could not find zlib library in ${ZLIB_INSTALL_DIR}/lib")
endif()

add_library(zlib_external_lib UNKNOWN IMPORTED GLOBAL)
set_target_properties(zlib_external_lib PROPERTIES
    IMPORTED_LOCATION "${ZLIB_LIB_FILE}"
    INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INSTALL_DIR}/include"
)

# ===========================================
# 2) SDL2 (release-2.32.10.zip → SDL-release-2.32.10)
# ===========================================
set(SDL2_ARCHIVE      "${THIRDPARTY_DIR}/release-2.32.10.zip")
set(SDL2_SRC_DIR      "${THIRDPARTY_DIR}/SDL-release-2.32.10")
set(SDL2_BUILD_DIR    "${SDL2_SRC_DIR}/build")
set(SDL2_INSTALL_DIR  "${SDL2_SRC_DIR}/install")

if(NOT EXISTS "${SDL2_ARCHIVE}")
    log("Downloading SDL2 release-2.32.10.zip ...")
    file(DOWNLOAD
        "https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.32.10.zip"
        "${SDL2_ARCHIVE}"
        SHOW_PROGRESS
    )
endif()

if(NOT EXISTS "${SDL2_SRC_DIR}/CMakeLists.txt")
    log("Extracting SDL2 archive to SDL-release-2.32.10 ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND} -E tar xvf "${SDL2_ARCHIVE}"
        WORKING_DIRECTORY "${THIRDPARTY_DIR}"
        RESULT_VARIABLE _sdl_extract_res
    )
    if(NOT _sdl_extract_res EQUAL 0)
        message(FATAL_ERROR "Failed to extract SDL2 archive")
    endif()
endif()

file(MAKE_DIRECTORY "${SDL2_BUILD_DIR}")

set(_have_sdl2 FALSE)
foreach(candidate
    "${SDL2_INSTALL_DIR}/lib/SDL2.lib"
    "${SDL2_INSTALL_DIR}/lib/SDL2-static.lib"
    "${SDL2_INSTALL_DIR}/lib/SDL2d.lib"
)
    if(EXISTS "${candidate}")
        set(_have_sdl2 TRUE)
        break()
    endif()
endforeach()

if(NOT _have_sdl2)
    log("Configuring SDL2 ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            -G "${CMAKE_GENERATOR}"
            -S "${SDL2_SRC_DIR}"
            -B "${SDL2_BUILD_DIR}"
            -DCMAKE_INSTALL_PREFIX=${SDL2_INSTALL_DIR}
            -DCMAKE_PREFIX_PATH=${ZLIB_INSTALL_DIR}   # путь к zlib для SDL2
        RESULT_VARIABLE _sdl_cfg_res
    )
    if(NOT _sdl_cfg_res EQUAL 0)
        message(FATAL_ERROR "SDL2 configure failed")
    endif()

    log("Building SDL2 (Debug) ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            --build "${SDL2_BUILD_DIR}" --config Debug
        RESULT_VARIABLE _sdl_build_res
    )
    if(NOT _sdl_build_res EQUAL 0)
        message(FATAL_ERROR "SDL2 build failed")
    endif()

    log("Installing SDL2 (Debug) ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            --install "${SDL2_BUILD_DIR}" --config Debug
        RESULT_VARIABLE _sdl_inst_res
    )
    if(NOT _sdl_inst_res EQUAL 0)
        message(FATAL_ERROR "SDL2 install failed")
    endif()
endif()

set(SDL2_LIB_FILE "")
foreach(candidate
    "${SDL2_INSTALL_DIR}/lib/SDL2.lib"
    "${SDL2_INSTALL_DIR}/lib/SDL2-static.lib"
    "${SDL2_INSTALL_DIR}/lib/SDL2d.lib"
)
    if(EXISTS "${candidate}")
        set(SDL2_LIB_FILE "${candidate}")
        break()
    endif()
endforeach()
if(SDL2_LIB_FILE STREQUAL "")
    message(FATAL_ERROR "Could not find SDL2 library in ${SDL2_INSTALL_DIR}/lib")
endif()

set(SDL2MAIN_LIB_FILE "")
if(EXISTS "${SDL2_INSTALL_DIR}/lib/SDL2main.lib")
    set(SDL2MAIN_LIB_FILE "${SDL2_INSTALL_DIR}/lib/SDL2main.lib")
endif()

add_library(SDL2_external_lib UNKNOWN IMPORTED GLOBAL)
set_target_properties(SDL2_external_lib PROPERTIES
    IMPORTED_LOCATION "${SDL2_LIB_FILE}"
    # Оба include-пути: и include, и include/SDL2
    INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INSTALL_DIR}/include;${SDL2_INSTALL_DIR}/include/SDL2"
)

if(NOT SDL2MAIN_LIB_FILE STREQUAL "")
    add_library(SDL2main_external_lib UNKNOWN IMPORTED GLOBAL)
    set_target_properties(SDL2main_external_lib PROPERTIES
        IMPORTED_LOCATION "${SDL2MAIN_LIB_FILE}"
        INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INSTALL_DIR}/include"
    )
endif()

# ===========================================
# 3) libpng (v1.6.51.zip → libpng-1.6.51)
#    ВАЖНО: не вызываем "cmake --install",
#    берём .lib из build/Debug
# ===========================================
set(LIBPNG_ARCHIVE      "${THIRDPARTY_DIR}/v1.6.51.zip")
set(LIBPNG_SRC_DIR      "${THIRDPARTY_DIR}/libpng-1.6.51")
set(LIBPNG_BUILD_DIR    "${LIBPNG_SRC_DIR}/build")
set(LIBPNG_INSTALL_DIR  "${LIBPNG_SRC_DIR}/install")  # на будущее

if(NOT EXISTS "${LIBPNG_ARCHIVE}")
    log("Downloading libpng v1.6.51.zip ...")
    file(DOWNLOAD
        "https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.51.zip"
        "${LIBPNG_ARCHIVE}"
        SHOW_PROGRESS
    )
endif()

if(NOT EXISTS "${LIBPNG_SRC_DIR}/CMakeLists.txt")
    log("Extracting libpng v1.6.51.zip to libpng-1.6.51 ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND} -E tar xvf "${LIBPNG_ARCHIVE}"
        WORKING_DIRECTORY "${THIRDPARTY_DIR}"
        RESULT_VARIABLE _png_extract_res
    )
    if(NOT _png_extract_res EQUAL 0)
        message(FATAL_ERROR "Failed to extract libpng archive")
    endif()
endif()

file(MAKE_DIRECTORY "${LIBPNG_BUILD_DIR}")

# Проверяем, есть ли уже .lib (build/Debug или install/lib)
set(_have_png FALSE)
set(_libpng_candidates
    "${LIBPNG_BUILD_DIR}/Debug/libpng16_staticd.lib"
    "${LIBPNG_BUILD_DIR}/Debug/libpng16d.lib"
    "${LIBPNG_BUILD_DIR}/Debug/png16d.lib"
    "${LIBPNG_BUILD_DIR}/libpng16_staticd.lib"
    "${LIBPNG_BUILD_DIR}/libpng16d.lib"
    "${LIBPNG_INSTALL_DIR}/lib/libpng16_staticd.lib"
    "${LIBPNG_INSTALL_DIR}/lib/libpng16d.lib"
    "${LIBPNG_INSTALL_DIR}/lib/png16d.lib"
)

foreach(candidate IN LISTS _libpng_candidates)
    if(EXISTS "${candidate}")
        set(_have_png TRUE)
        break()
    endif()
endforeach()

if(NOT _have_png)
    log("Configuring libpng ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            -G "${CMAKE_GENERATOR}"
            -S "${LIBPNG_SRC_DIR}"
            -B "${LIBPNG_BUILD_DIR}"
            -DCMAKE_INSTALL_PREFIX=${LIBPNG_INSTALL_DIR}
            -DCMAKE_PREFIX_PATH=${ZLIB_INSTALL_DIR}
            -DZLIB_ROOT=${ZLIB_INSTALL_DIR}
        RESULT_VARIABLE _png_cfg_res
    )
    if(NOT _png_cfg_res EQUAL 0)
        message(FATAL_ERROR "libpng configure failed")
    endif()

    log("Building libpng (Debug) ...")
    execute_process(
        COMMAND ${CMAKE_COMMAND}
            --build "${LIBPNG_BUILD_DIR}" --config Debug
        RESULT_VARIABLE _png_build_res
    )
    if(NOT _png_build_res EQUAL 0)
        message(FATAL_ERROR "libpng build failed")
    endif()

    # без --install, чтобы не упереться в INSTALL target
endif()

# Ищем конкретный .lib для линковки
set(LIBPNG_LIB_FILE "")
foreach(candidate IN LISTS _libpng_candidates)
    if(EXISTS "${candidate}")
        set(LIBPNG_LIB_FILE "${candidate}")
        break()
    endif()
endforeach()
if(LIBPNG_LIB_FILE STREQUAL "")
    message(FATAL_ERROR "Could not find libpng library (checked build/Debug and install/lib)")
endif()

add_library(libpng_external_lib UNKNOWN IMPORTED GLOBAL)
set_target_properties(libpng_external_lib PROPERTIES
    IMPORTED_LOCATION "${LIBPNG_LIB_FILE}"
    # png.h, pngconf.h – в SRC, pnglibconf.h – в BUILD
    INTERFACE_INCLUDE_DIRECTORIES "${LIBPNG_SRC_DIR};${LIBPNG_BUILD_DIR}"
)

# ===========================================
# Основной проект space_game001
# ===========================================
add_executable(space_game001
    main.cpp
    Game.cpp
    Game.h
    Environment.cpp
    Environment.h
    Renderer.cpp
    Renderer.h
    ShaderManager.cpp
    ShaderManager.h
    TextureManager.cpp
    TextureManager.h
    TextModel.cpp
    TextModel.h
    AudioPlayerAsync.cpp
    AudioPlayerAsync.h
    BoneAnimatedModel.cpp
    BoneAnimatedModel.h
    Math.cpp
    ZLMath.h
    OpenGlExtensions.cpp
    OpenGlExtensions.h
    Utils.cpp
    Utils.h
)

# include-пути проекта
target_include_directories(space_game001 PRIVATE
    "${CMAKE_CURRENT_SOURCE_DIR}"
    "${CMAKE_CURRENT_SOURCE_DIR}/gl"
    "${CMAKE_CURRENT_SOURCE_DIR}/cmakeaudioplayer/include"
    "${SDL2_INSTALL_DIR}/include"
    "${SDL2_INSTALL_DIR}/include/SDL2"
)

set_target_properties(space_game001 PROPERTIES
    OUTPUT_NAME "space-game001"
)

# Определения препроцессора:
# PNG_ENABLED – включает код PNG в TextureManager
# SDL_MAIN_HANDLED – отключает переопределение main -> SDL_main
target_compile_definitions(space_game001 PRIVATE
    PNG_ENABLED
    SDL_MAIN_HANDLED
)

# Линкуем с SDL2main, если он вообще установлен
if(TARGET SDL2main_external_lib)
    target_link_libraries(space_game001 PRIVATE SDL2main_external_lib)
endif()

# Линкуем сторонние библиотеки
target_link_libraries(space_game001 PRIVATE
    SDL2_external_lib
    libpng_external_lib
    zlib_external_lib
)

# Линкуем OpenGL (Windows)
if(WIN32)
    target_link_libraries(space_game001 PRIVATE opengl32)
endif()

# ===========================================
# Копирование SDL2d.dll и zlibd.dll рядом с exe
# ===========================================
if (WIN32)
    add_custom_command(TARGET space_game001 POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E echo "Copying SDL2d.dll and zlibd.dll to output folder..."
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${SDL2_BUILD_DIR}/Debug/SDL2d.dll"
            "$<TARGET_FILE_DIR:space_game001>/SDL2d.dll"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${ZLIB_BUILD_DIR}/Debug/zlibd.dll"
            "$<TARGET_FILE_DIR:space_game001>/zlibd.dll"
    )
endif()


# ===========================================
# Копирование ресурсов после сборки
# ===========================================

# Какие папки с ресурсами нужно копировать
set(RUNTIME_RESOURCE_DIRS
    "resources"
    "shaders"
)

# Копируем ресурсы и шейдеры в папку exe и в корень build/
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
    add_custom_command(TARGET space_game001 POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to runtime folders..."
        # 1) туда, где лежит exe (build/Debug, build/Release и т.п.)
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${CMAKE_SOURCE_DIR}/${resdir}"
            "$<TARGET_FILE_DIR:space_game001>/${resdir}"
        # 2) в корень build, если захочешь запускать из этой папки
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${CMAKE_SOURCE_DIR}/${resdir}"
            "${CMAKE_BINARY_DIR}/${resdir}"
    )
endforeach()
