cmake_minimum_required(VERSION 3.17)

# Alpho Vivy, CXX only
project(Vivy VERSION 0.1 LANGUAGES CXX)
cmake_policy(SET CMP0100 NEW) # Let cmake use moc and uic for .hh files
cmake_policy(SET CMP0009 NEW) # Do not follow symlinks with GLOB_RECURSE

# Don't forget for specific things
if(WIN32)
    message(STATUS "You are building on windows, pay attenion to the dependencies")
endif()
if(MSVC OR MSYS OR MINGW)
    message(STATUS "You are building with a windows compiler")
endif()
if(APPLE)
    message(STATUS "You are building on MacOS X")
endif()
if(UNIX AND NOT APPLE)
    message(STATUS "You are building on Linux, FreeBSD or any other toaster OS")
endif()

# Pass -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# For Qt
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

# Pthread ftw
set(THREADS_PREFER_PTHREAD_FLAG ON)

# Find Qt dependencies
find_package(QT NAMES Qt6 Qt5      COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)

# Find others dependencies
find_library(AVCODEC_LIBRARY    avcodec     4.0 REQUIRED)
find_library(AVUTIL_LIBRARY     avutil      4.0 REQUIRED)
find_library(SWRESAMPLE_LIBRARY swresample      REQUIRED)
find_library(AVFORMAT_LIBRARY   avformat        REQUIRED)
find_library(MPV_LIBRARY        mpv             REQUIRED)

# Add the lua dependency
add_subdirectory(
    "${CMAKE_CURRENT_SOURCE_DIR}/vendor/lua-5.4.3"
    "${CMAKE_BINARY_DIR}/vendor/lua-5.4.3"
)

# Grab all files
file(GLOB_RECURSE Vivy_SRC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc")
file(GLOB_RECURSE Vivy_INC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.hh")
if(APPLE)
    file(GLOB_RECURSE Vivy_APPLE_SRC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.mm")
endif()
set(PROJECT_SOURCES ${Vivy_SRC} ${Vivy_INC} ${Vivy_APPLE_SRC})

# Add the Vivy executable
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(Vivy
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
        rsc/VivyRessources.qrc
    )
else()
    add_executable(Vivy
        ${PROJECT_SOURCES}
        rsc/VivyRessources.qrc
    )
endif()

# Link dependencies to Vivy
target_link_libraries(Vivy PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(Vivy PRIVATE ${AVCODEC_LIBRARY})
target_link_libraries(Vivy PRIVATE ${AVUTIL_LIBRARY})
target_link_libraries(Vivy PRIVATE ${SWRESAMPLE_LIBRARY})
target_link_libraries(Vivy PRIVATE ${AVFORMAT_LIBRARY})
target_link_libraries(Vivy PRIVATE ${MPV_LIBRARY})
target_link_libraries(Vivy PRIVATE lua)

# Headers related things
include("${CMAKE_CURRENT_SOURCE_DIR}/PreCompiledHeaders.cmake")
target_include_directories(Vivy PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_precompile_headers(Vivy PRIVATE ${Vivy_PRECOMPILED_INC})

# Set Vivy's needed C++ features
target_compile_features(Vivy PRIVATE
    cxx_std_20
    cxx_auto_type
    cxx_deleted_functions
    cxx_explicit_conversions
    cxx_final
    cxx_inline_namespaces
    cxx_lambdas
    cxx_noexcept
    cxx_nonstatic_member_init
    cxx_nullptr
    cxx_override
    cxx_range_for
    cxx_strong_enums
)

# More options and warnings
target_compile_options(Vivy PRIVATE
    -Wall -Wextra -Wpedantic
    -Wshadow
    -Wcast-align
    -Wconversion
    -Wsign-conversion
    -Wunused-variable
    -Wmisleading-indentation
    -Wnull-dereference
    -Wdouble-promotion
    -Wformat=2
    -Woverloaded-virtual
    -Wnon-virtual-dtor
    -Wignored-qualifiers

    -fopenmp
)

target_link_libraries(Vivy PRIVATE -fopenmp)

# Prepare for Qt6
target_compile_definitions(Vivy PRIVATE
    QT_DISABLE_DEPRECATED_BEFORE=0x050F00
    QT_NO_CAST_TO_ASCII
    QT_RESTRICTED_CAST_FROM_ASCII
    QTCREATOR_UTILS_STATIC_LIB
)

# Some compiler specific warnings and options
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
    target_compile_options(Vivy PRIVATE
        -Weverything

        # Disable some things because we want C++20 and don't control some Qt
        # generated files...
        -Wno-c++98-compat
        -Wno-c++98-compat-pedantic
        -Wno-c++98-c++11-c++14-c++17-compat-pedantic
        -Wno-c++20-compat

        -Wno-extra-semi-stmt
        -Wno-redundant-parens
        -Wno-padded
        -Wno-global-constructors
        -Wno-exit-time-destructors
    )
    target_link_libraries(Vivy PRIVATE
        -fopenmp
    )
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
    target_compile_options(Vivy PRIVATE
        -fopenmp
        -Wno-subobject-linkage  # Kubat: Some proglems here, it seems they
                                # occure because of the usage of "using" for
                                # type aliasing... As I won't get ride of the
                                # "using"s the warning is disabled
    )
endif()

set_target_properties(Vivy PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER vivy.iiens.net
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(Vivy)
endif()

# Set ASAN
if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug")
    if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
        target_compile_options(Vivy PRIVATE -g -O1 -fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-return=always)
    elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
        target_compile_options(Vivy PRIVATE -g -O1 -fsanitize=address -fno-omit-frame-pointer)
    endif()

    target_link_libraries(Vivy PRIVATE -g -O1 -fsanitize=address)
endif()