cmake_minimum_required(VERSION 3.20)
project(CPP_TEMPLATE VERSION 0.1.0 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Set output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# Add include directories
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/libraries)

# Gather all source files (.cpp, .c) — but NOT glad.c
file(GLOB_RECURSE PROJECT_SOURCES
    ${CMAKE_SOURCE_DIR}/include/*.cpp
    ${CMAKE_SOURCE_DIR}/include/*.c
    ${CMAKE_SOURCE_DIR}/source/*.cpp
    ${CMAKE_SOURCE_DIR}/source/*.c
)

# Gather all header files (.hpp, .h)
file(GLOB_RECURSE PROJECT_HEADERS
    ${CMAKE_SOURCE_DIR}/include/*.hpp
    ${CMAKE_SOURCE_DIR}/include/*.h
    ${CMAKE_SOURCE_DIR}/libraries/*.hpp
    ${CMAKE_SOURCE_DIR}/libraries/*.h
    ${CMAKE_SOURCE_DIR}/source/*.hpp
    ${CMAKE_SOURCE_DIR}/source/*.h
)

# Allow user to set output program name
option(OUTPUT_NAME "Name of the output executable" "")
if(OUTPUT_NAME STREQUAL "")
    set(EXECUTABLE_NAME ${PROJECT_NAME})
else()
    set(EXECUTABLE_NAME ${OUTPUT_NAME})
endif()

# Add executable with all sources
add_executable(${EXECUTABLE_NAME}
    ${PROJECT_SOURCES}
    ${PROJECT_HEADERS}
)

# Set output name property (for consistency)
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_NAME})

# Enable warnings and extra diagnostics
if (MSVC)
    target_compile_options(${EXECUTABLE_NAME} PRIVATE /W4 /permissive- /analyze)
else()
    target_compile_options(${EXECUTABLE_NAME} PRIVATE
        -Wall
        -Wextra
        -Wpedantic
        -Wshadow
        -Wconversion
        -Wsign-conversion
        -Wuninitialized
        -Wunused
        -Werror=return-type
        -fsanitize=address,undefined
        -g
    )
    target_link_options(${EXECUTABLE_NAME} PRIVATE -fsanitize=address,undefined)
endif()

# -----------------------
# External Dependencies
# -----------------------

# GLFW (if vendored in libraries/)
if(EXISTS ${CMAKE_SOURCE_DIR}/libraries/glfw/CMakeLists.txt)
    add_subdirectory(${CMAKE_SOURCE_DIR}/libraries/glfw EXCLUDE_FROM_ALL)
endif()

# GLM (header-only)
if(EXISTS ${CMAKE_SOURCE_DIR}/libraries/glm/CMakeLists.txt)
    add_subdirectory(${CMAKE_SOURCE_DIR}/libraries/glm EXCLUDE_FROM_ALL)
endif()

# GLAD (build once as a static lib)
if(EXISTS ${CMAKE_SOURCE_DIR}/libraries/glad/src/glad.c)
    add_library(glad ${CMAKE_SOURCE_DIR}/libraries/glad/src/glad.c)
    target_include_directories(glad PUBLIC ${CMAKE_SOURCE_DIR}/libraries/glad/include)
endif()

# Link with OpenGL + dependencies
if (APPLE)
    target_link_libraries(${EXECUTABLE_NAME} PRIVATE glfw glad glm::glm "-framework OpenGL")
elseif (UNIX)
    find_package(OpenGL REQUIRED)
    target_link_libraries(${EXECUTABLE_NAME} PRIVATE glfw glad glm::glm OpenGL::GL)
elseif (WIN32)
    target_link_libraries(${EXECUTABLE_NAME} PRIVATE glfw glad glm::glm opengl32)
endif()

# Optionally, enable testing
# enable_testing()
# add_subdirectory(tests)

