cmake_minimum_required(VERSION 3.30)

project(
        kuiper-engine
        VERSION 0.1
        DESCRIPTION "Kuiper Engine"
        LANGUAGES CXX
)

# Required by Kuiper Engine, but needs to be explicitly specified for Abseil, at least
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_library(
        kuiper
        STATIC
        src/cli/cli.cpp
        src/core/engine.cpp
        src/core/io.cpp
        src/core/entrypoint.cpp
        src/graphics/opengl/buffer.cpp
        src/graphics/opengl/framebuffer.cpp
        src/graphics/opengl/texture.cpp
        src/graphics/opengl/texture_array.cpp
        src/graphics/opengl/shader.cpp
        src/graphics/opengl/program.cpp
        src/graphics/opengl/render_context.cpp
        src/graphics/opengl/vertex_array.cpp
        src/resources/image.cpp
        src/resources/model.cpp
        src/resources/resource_index.cpp
        src/resources/resource_manager.cpp
        src/platform/glfw/glfw_window.cpp
        src/renderer/gl_renderer.cpp
        src/window/input_system.cpp
)

target_compile_features(kuiper PUBLIC cxx_std_23)
if(CXX_STANDARD LESS 23)
    message(FATAL_ERROR
        "Kuiper Engine requires CXX_STANDARD >= 23 (got: ${CXX_STANDARD})")
endif()

target_include_directories(kuiper PUBLIC "include/")

# Compiler options
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
    # GCC & Clang
    message(STATUS "Adding GCC & Clang-specific compiler options")
    if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
        target_compile_options(kuiper PRIVATE -Wall)
    elseif (${CMAKE_BUILD_TYPE} STREQUAL "Release")
        target_compile_options(kuiper PRIVATE -O3)
    endif ()
endif ()

# Binary resource inclusion because std::embed still isn't here
# TODO: do this in a loop: https://cmake.org/cmake/help/book/mastering-cmake/chapter/Custom%20Commands.html#adding-a-custom-target

find_program(
    BIN2HPP_FOUND
    bin2hpp
    REQUIRED
)

set(EMBEDDED_SHADERS_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp)
file(MAKE_DIRECTORY ${EMBEDDED_SHADERS_DIR})

# Vertex shader
add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/default_vs.hpp
        COMMAND bin2hpp -i "${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/geometry.vert" -o "${EMBEDDED_SHADERS_DIR}/default_vs.hpp" -n bin -s default_vs
)

# Fragment shader
add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/default_fs.hpp
        COMMAND bin2hpp -i "${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/pbr.frag" -o "${EMBEDDED_SHADERS_DIR}/default_fs.hpp" -n bin -s default_fs
)

# Clustering computer shader
add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/clustering_cs.hpp
        COMMAND bin2hpp -i "${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/build_clusters.comp" -o "${EMBEDDED_SHADERS_DIR}/clustering_cs.hpp" -n bin -s clustering_cs
)

# Light-culling computer shader
add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/light_culling_cs.hpp
        COMMAND bin2hpp -i "${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/cull_lights.comp" -o "${EMBEDDED_SHADERS_DIR}/light_culling_cs.hpp" -n bin -s light_culling_cs
)

add_custom_target(
        embedded-shaders
        ALL
        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/default_vs.hpp
        ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/default_fs.hpp
        ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/clustering_cs.hpp
        ${CMAKE_CURRENT_BINARY_DIR}/bin2hpp/light_culling_cs.hpp
)
add_dependencies(kuiper embedded-shaders)

target_include_directories(kuiper PUBLIC ${EMBEDDED_SHADERS_DIR})

# Dependencies

include(FetchContent)
target_link_libraries(kuiper PUBLIC glad glfw glm::glm spdlog imgui stb freetype fastgltf flecs::flecs_static)
target_link_libraries(kuiper PRIVATE absl::flat_hash_map)

# GLAD
add_subdirectory("thirdparty/glad/")

# GLFW
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
        glfw
        GIT_REPOSITORY https://github.com/glfw/glfw.git
        GIT_TAG 3.4
        OVERRIDE_FIND_PACKAGE # For use with find_package()
)
FetchContent_MakeAvailable(glfw)
# find_package(glfw3 3.4 REQUIRED)

# OpenGL Mathematics (GLM)
FetchContent_Declare(
        glm
        GIT_REPOSITORY https://github.com/g-truc/glm.git
        GIT_TAG 1.0.1
)
FetchContent_MakeAvailable(glm)

# spdlog
set(SPDLOG_USE_STD_FORMAT ON CACHE BOOL "" FORCE)
set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "" FORCE)
set(SPDLOG_BUILD_EXAMPLE_HO OFF CACHE BOOL "" FORCE)
set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(SPDLOG_BUILD_TESTS_HO OFF CACHE BOOL "" FORCE)
set(SPDLOG_BUILD_BENCH OFF CACHE BOOL "" FORCE)
set(SPDLOG_DISABLE_DEFAULT_LOGGER ON CACHE BOOL "" FORCE)

FetchContent_Declare(
        spdlog
        GIT_REPOSITORY https://github.com/gabime/spdlog.git
        GIT_TAG v1.14.1
)
FetchContent_MakeAvailable(spdlog)

# UTF8-CPP
target_include_directories(kuiper PRIVATE "thirdparty/utfcpp/include/")

# FreeType
set(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE)
set(FT_DISABLE_BZIP2 ON CACHE BOOL "" FORCE)
set(FT_DISABLE_HARFBUZZ ON CACHE BOOL "" FORCE)
set(FT_DISABLE_PNG ON CACHE BOOL "" FORCE)
set(FT_DISABLE_ZLIB ON CACHE BOOL "" FORCE)
set(FT_ENABLE_ERROR_STRINGS OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
        freetype
        URL https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.gz
        URL_HASH SHA256=5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747
        OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(freetype)

# simdjson (note: also a dependency of fastgltf)
set(SIMDJSON_DEVELOPER_MODE OFF CACHE BOOL "" FORCE)
set(SIMDJSON_DISABLE_DEPRECATED_API ON CACHE BOOL "" FORCE)

FetchContent_Declare(
        simdjson
        GIT_REPOSITORY https://github.com/simdjson/simdjson.git
        GIT_TAG v3.11.3
        OVERRIDE_FIND_PACKAGE # So fastgltf can find it
)
FetchContent_MakeAvailable(simdjson)

# fastgltf
set(FASTGLTF_COMPILE_AS_CPP20 ON CACHE BOOL "" FORCE)

FetchContent_Declare(
        fastgltf
        GIT_REPOSITORY https://github.com/spnda/fastgltf.git
        GIT_TAG v0.8.0
)
FetchContent_MakeAvailable(fastgltf)

# flecs
set(FLECS_SHARED OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
        flecs
        GIT_REPOSITORY https://github.com/SanderMertens/flecs.git
        GIT_TAG v4.0.4
)
FetchContent_MakeAvailable(flecs)

# Abseil C++
set(ABSL_BUILD_TESTING OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
        abseil
        GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git
        GIT_TAG 20250127.1
)
FetchContent_MakeAvailable(abseil)

# Dear ImGui
add_subdirectory("thirdparty/imgui/")

# STB
add_subdirectory("thirdparty/stb/")
