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)
file(GLOB_RECURSE PROJECT_SOURCES
    ${CMAKE_SOURCE_DIR}/include/*.cpp
    ${CMAKE_SOURCE_DIR}/include/*.c
    ${CMAKE_SOURCE_DIR}/libraries/*.cpp
    ${CMAKE_SOURCE_DIR}/libraries/*.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}
)

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()

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