# Nous voulons un cmake "récent" pour utiliser les dernières fonctionnalités.
cmake_minimum_required(VERSION 3.20)
set (CMAKE_CXX_STANDARD 23)
# Nom du projet.
set(PROJECT CosmicEngine)
project(${PROJECT})

# Génération de la liste des fichiers sources.
file(GLOB_RECURSE
    SRCS_ENGINE
    src/Engine/*
)

file(GLOB_RECURSE
    SRCS
    src/main.cpp)

file(GLOB_RECURSE
    SRCS_TESTS
    test/*
)

# ---------- Inclusion des packages sous windows -----------
if(WIN32)
endif()
# ---------- Inclusion des packages sous mac -----------
if(APPLE)
endif()
# ---------- Inclusion des packages sous linux -----------

if(UNIX)
# --------- Inclusion d'OpenGL ----------
# OpenGL Lib pour charger OpenGL, fournit avec les drivers, donc se trouve toute seul.
    # find_package(OpenGL REQUIRED)
    # if(OPENGL_FOUND)
    #     message("lib OpenGL Trouvé")
    # else()
    #     message("lib OpenGL Introuvable")
    # endif()
# ---------------------------------------

# --------- Inclusion de Vulkan ----------
# Vulkan Lib pour charger Vulkan, fournit avec les drivers, donc se trouve toute seul.
    # find_package(Vulkan REQUIRED)
    # if(VULKAN_FOUND)
    #     message("lib OpenGL Trouvé")
    # else()
    #     message("lib OpenGL Introuvable")
    # endif()
# ---------------------------------------

# ---------- Inclusion de GLM -----------
# GLM Lib pour mathématique, en mode header only.
    set(GLMlib_DIR ./lib/CMake/Linux)
    find_package(GLMlib REQUIRED)
    if(GLMlib_FOUND)
        message("lib GLM Trouvé")
    else()
        message("lib GLM Introuvable")
    endif()
# ---------------------------------------

# ------- Inclusion de JSONfMC++ --------
# JSONfMC++ Lib pour gestion fichier JSON, en mode header only.
    set(JSONlib_DIR ./lib/CMake/Linux)
    find_package(JSONlib REQUIRED)

    if(JSONlib_FOUND)
        message("lib JSONFMC++ Trouvé")
    else()
        message("lib JSONFMC++ Introuvable")
    endif()
# ---------------------------------------

# ------- Inclusion de EnTT --------
# EnTT Lib pour gestion fichier JSON, en mode header only.
     set(EnTTlib_DIR ./lib/CMake/Linux)
     find_package(EnTTlib REQUIRED)

     if(EnTTlib_FOUND)
         message("lib EnTTlib Trouvé")
     else()
         message("lib EnTTlib Introuvable")
     endif()


# --------- Inclusion de Boost ----------
# Boost Lib pour diverse simplification
    # set(Boost_USE_STATIC_LIBS OFF) 
    # set(Boost_USE_MULTITHREADED ON)  
    # set(Boost_USE_STATIC_RUNTIME OFF) 

    # find_package(Boost REQUIRED COMPONENTS log_setup log filesystem chrono thread date_time regex) # header only libraries must not be added here

    # message(STATUS "Boost version: ${Boost_VERSION}")

    # if(NOT TARGET Boost::filesystem)
    #     add_library(Boost::filesystem IMPORTED INTERFACE)
    #     set_property(TARGET Boost::filesystem PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::filesystem PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(NOT TARGET Boost::thread)
    #     add_library(Boost::thread IMPORTED INTERFACE)
    #     set_property(TARGET Boost::thread PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::thread PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(NOT TARGET Boost::chrono)
    #     add_library(Boost::chrono IMPORTED INTERFACE)
    #     set_property(TARGET Boost::chrono PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::chrono PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(NOT TARGET Boost::date_time)
    #     add_library(Boost::date_time IMPORTED INTERFACE)
    #     set_property(TARGET Boost::date_time PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::date_time PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(NOT TARGET Boost::regex)
    #     add_library(Boost::regex IMPORTED INTERFACE)
    #     set_property(TARGET Boost::regex PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::regex PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(NOT TARGET Boost::log)
    #     add_library(Boost::log IMPORTED INTERFACE)
    #     set_property(TARGET Boost::log PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::log PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(NOT TARGET Boost::log_setup)
    #     add_library(Boost::log_setup IMPORTED INTERFACE)
    #     set_property(TARGET Boost::log_setup PROPERTY
    #         INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
    #     set_property(TARGET Boost::log_setup PROPERTY
    #         INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
    # endif()

    # if(Boost_FOUND)
    #     message("lib Boost Trouvé")
    # else()
    #     message("lib Boost Introuvable")
    # endif()
# ---------------------------------------

# -------- Inclusion de la SDL2 ----------
# SDL2 Lib pour fenetre et contrôle

# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
    # find_package(SDL2 REQUIRED)
    # if(SDL2_FOUND)
    #     message("lib SDL2 Trouvé")
    # else()
    #     message("lib SDL2 Introuvable")
    # endif()
# ---------------------------------------

# ------- Inclusion de SDL2_IMAGE --------
# SDL2_IMAGE Lib pour charger une image
    # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.   
    # find_package(SDL2_image QUIET)
    # #find_library(SDL2_image libSDL2_image)

    # if(SDL2_image_FOUND)
    #     message("lib SDL2_IMAGE Trouvé")
    # else()
    #     message("lib SDL2_IMAGE Introuvable")
    # endif()
# ---------------------------------------

# ------- Inclusion de SDL2_TTF --------
# SDL2_IMAGE Lib pour charger une police d'écriture.
    # set(SDL2_ttf_DIR ./lib/CMake/Linux)
    # # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
    # find_package(SDL2_ttf QUIET)
    # #find_library(SDL2_ttf libSDL2_ttf)
    # if(SDL2_ttf_FOUND)
    #     message("lib SDL2_TTF Trouvé")
    # else()
    #     message("lib SDL2_TTF Introuvable")
    # endif()
# ---------------------------------------

# --------- Inclusion de GLEW -----------
# GLEW Lib pour charger utiliser OpenGL + extension
    # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
    # find_package(GLEW REQUIRED)
    # if(GLEW_FOUND)
    #     message("lib GLEW Trouvé")
    # else()
    #     message("lib GLEW Introuvable")
    # endif()  
# ---------------------------------------

# ---------- Inclusion de ASSIMP -----------
# Assimp Lib import modèles 3D.
    # find_package(assimp REQUIRED)
    # if(assimp_FOUND)
    #     message("lib ASSIMP Trouvé")
    # else()
    #     message("lib ASSIMP Introuvable")
    # endif()  
# ---------------------------------------

# ---------- Inclusion de ODE -----------
# ODE Lib Moteur physique.
    # set(ODE_DIR ./lib/CMake/Linux)
    # # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
    # find_package(ODE REQUIRED)
    # if(ODE_FOUND)
    #     message("lib ODE Trouvé")
    # else()
    #     message("lib ODE Introuvable")
    # endif()
# ---------------------------------------

# --------- Inclusion de SNDFILE ----------
# SNDFILE Lib pour inclure le son.
    # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
    #set(SNDFILE_DIR ./lib/CMake/Linux)
    # find_package(sndfile QUIET)#TODO corrige
    # #find_library(sndfile libsndfile)
    # if(sndfile_FOUND)
    #     message("lib SNDFILE Trouvé")
    # else()
    #     message("lib SNDFILE Introuvable")
    # endif()  
# ---------------------------------------

# ---------- Inclusion de OpenAL-----------
# OpenAL Lib gérer le son.
    # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. 
    # set(OPENAL_DIR ./lib/CMake/Linux)  
    # find_package(OPENAL REQUIRED)

    # if(OPENAL_FOUND)
    #     message("lib OpenAL Trouvé")
    # else()
    #     message("lib OpenAL Introuvable")
    # endif()
# ---------------------------------------

# ---------- Inclusion de Catch2-----------
# Gestion des tests unitaires

find_package(Catch2 3 REQUIRED)
# These tests can use the Catch2-provided main
if(Catch2_found)
    message("lib Catch2 Trouvé")
else()
    message("lib Catch2 Introuvable")
endif()

endif()
# Chemin executable
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/${CMAKE_BUILD_TYPE}")

# On indique que l'on veut un exécutable nommé PROJECT compilé à partir des fichiers décrits par les variables SRCS et HEADERS.

add_library(Engine SHARED ${SRCS_ENGINE} ${SRCS_EXTERNAL_GLAD})
add_executable(${PROJECT} ${SRCS})
add_dependencies(${PROJECT} Engine)

add_executable(CosmicTest ${SRCS_TESTS})
target_link_libraries(CosmicTest PRIVATE Catch2::Catch2WithMain Engine)

# Fichier include
# OpenGL
#include_directories(${OPENGL_INCLUDE_DIR})
# SDL2
#include_directories(${SDL2_INCLUDE_DIRS})
# GLEW
#include_directories(${GLEW_INCLUDE_DIRS})
# SDL2_image
#include_directories(${SDL2_IMAGE_INCLUDE_DIRS})
# SDL2_ttf
#include_directories(${SDL2_TTF_INCLUDE_DIRS})
# GLM
include_directories(${GLM_INCLUDE_DIRS})
# JSONFMCPP
include_directories(${JSONFMCPP_INCLUDE_DIRS})
#ENTT
include_directories(${ENTT_INCLUDE_DIRS})

# ASSIMP
#include_directories(${ASSIMP_INCLUDE_DIRS})
# ODE
#include_directories(${ODE_INCLUDE_DIRS})
# SNDFILE
#include_directories(${SNDFILE_INCLUDE_DIRS})
# OPENAL
#include_directories(${OPENAL_INCLUDE_DIRS})

# Fichier lib
# OpenGL
#target_link_libraries(Engine OpenMP::OpenMP_CXX)

# OpenMP
#target_link_libraries(Engine ${OPENGL_LIBRARIES})

# SDL2
#target_link_libraries(Engine ${SDL2_LIBRARIES})

# GLEW
#target_link_libraries(Engine ${GLEW_LIBRARIES})

# SDL2_image
#target_link_libraries(Engine SDL2_image)

# SDL2_ttf
#target_link_libraries(Engine SDL2_ttf)

# Boost


# ASSIMP
#target_link_libraries(Engine ${ASSIMP_LIBRARIES})


# ODE
#target_link_libraries(Engine ${ODE_LIBRARIES})

# SNDFILE
#target_link_libraries(Engine sndfile)

# OPENAL
#target_link_libraries(Engine ${OPENAL_LIBRARIES})


#target_link_libraries(Engine ${CMAKE_DL_LIBS})

#target_link_libraries(${PROJECT} ${CMAKE_DL_LIBS})


# Boost
# target_link_libraries(Engine Boost::boost)
# target_link_libraries(Engine Boost::filesystem)
# target_link_libraries(Engine Boost::chrono)
# target_link_libraries(Engine Boost::thread)
# target_link_libraries(Engine Boost::date_time)
# target_link_libraries(Engine Boost::regex)
# target_link_libraries(Engine Boost::log)
# target_link_libraries(Engine Boost::log_setup)

target_link_libraries(${PROJECT} Engine)

if(UNIX)
add_custom_command(
        TARGET Engine POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_CURRENT_BINARY_DIR}/libEngine.so
                ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()			

# Paramètre de compilation
if (UNIX)
    set(CMAKE_CXX_FLAGS "-Wall -ldl -fPIC")
endif ()

# Valgrind ne marche que pour Linux...
if (UNIX)
    add_custom_target("valgrind"
        COMMAND ${CMAKE_CTEST_COMMAND} 
            --force-new-ctest-process --test-action memcheck
        COMMAND cat "${CMAKE_BINARY_DIR}/Testing/Temporary/MemoryChecker.*.log")
endif()

# Doxygen
# check if Doxygen is installed
find_package(Doxygen)
if (DOXYGEN_FOUND)
    # set input and output files
    set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in)
    set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/doc/Doxyfile)

    # request to configure the file
    configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
    message("Doxygen build started")

    # note the option ALL which allows to build the docs together with the application
    add_custom_target("doxygen"
        COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
        COMMENT "Generating API documentation with Doxygen"
        VERBATIM)
else()
    message("Doxygen need to be installed to generate the doxygen documentation")
endif()

foreach(source IN LISTS SRCS_ENGINE)
    get_filename_component(source_path "${source}" PATH)
    STRING(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" source_path ${source_path})
    string(REPLACE "/" "\\" source_path_msvc "${source_path}")
    source_group("${source_path_msvc}" FILES "${source}")
endforeach()

foreach(source IN LISTS SRCS)
    get_filename_component(source_path "${source}" PATH)
    STRING(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" source_path ${source_path})
    string(REPLACE "/" "\\" source_path_msvc "${source_path}")
    source_group("${source_path_msvc}" FILES "${source}")
endforeach()

message(STATUS "Tree reorganized")