cmake_minimum_required (VERSION 3.16.0)

if(POLICY CMP0071)
	cmake_policy(SET CMP0071 NEW)
endif()

# Set project name
project (openMittsu CXX C)

# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)

set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake/")
include(RegisterSourceGroup)
include(ExternalProject)
include(AddImportedLibrary)

message(STATUS "Target processor: ${CMAKE_SYSTEM_PROCESSOR}")

# SpdLog base path, included via GIT Submodule
set(SPDLOG_MODULE_BASEPATH "${PROJECT_SOURCE_DIR}/3rdparty/spdlog")

# SpdLog Configuration via #defines
add_definitions(-DSPDLOG_DEBUG_ON)

# Distribution info
set(OPENMITTSU_DIST True)
set(OPENMITTSU_DIST_TYPE "Other" CACHE STRING "OpenMittsu Distribution type")
set_property(CACHE OPENMITTSU_DIST_TYPE PROPERTY STRINGS Deb Zip Installer AppImage Other)
if(OPENMITTSU_DIST_TYPE STREQUAL "Snap")
  set(OPENMITTSU_DIST_SNAP True)
elseif(OPENMITTSU_DIST_TYPE STREQUAL "AppImage")
  set(OPENMITTSU_DIST_APPIMAGE True)
elseif(OPENMITTSU_DIST_TYPE STREQUAL "Other")
  unset(OPENMITTSU_DIST)
endif()

option(OPENMITTSU_ALLOW_MISSING_QSQLCIPHER "Sets whether OpenMittsu will run even with QSqlCipher being unavailable (no encryption)." OFF)
option(OPENMITTSU_LINK_LIBCXXABI "Sets whether libc++abi should be linked." OFF)
option(OPENMITTSU_USE_LIBCXX "Sets whether the standard library is libc++." OFF)
option(OPENMITTSU_DEBUG "Sets whether debug checks, assertions and logging should be turned on. Has no effect on builds under MSVC besides turning on debug logging level." OFF)
option(OPENMITTSU_DISABLE_VERSION_UPDATE_CHECK "Disables the version check on start-up. Useful for custom builds or added privacy." OFF)
option(OPENMITTSU_ENABLE_TESTS "Enables tests." ON)
option(OPENMITTSU_USE_NSIS "Use NSIS generator to produce a Windows installer." OFF)
option(OPENMITTSU_WITH_APP_BUNDLE "Enable Application Bundle for macOS" ON)

SET(OPENMITTSU_CMAKE_SEARCH_PATH "C:/Qt/6.10.0/msvc2022_64" CACHE PATH "Additional Qt5 search path" )
set(OPENMITTSU_CUSTOM_VERSION_STRING "" CACHE STRING "Disables Git version number checking and uses the custom string instead. Should be of the form 0.1.2-34-567890ab, i.e. major.minor.patch-commitsSinceTag-shortHash")

SET(CMAKE_PREFIX_PATH "${OPENMITTSU_CMAKE_SEARCH_PATH}/lib/cmake/")

SET(OPENMITTSU_ADDITIONAL_INSTALL_FILES "" CACHE STRING "A semicolon separated list of files that will be copied to the bin directory on install.")

if(APPLE AND WITH_APP_BUNDLE AND "${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local")
	set(CMAKE_INSTALL_PREFIX "/Applications")
	set(CMAKE_INSTALL_MANDIR "/usr/local/share/man")
endif()

if(MINGW OR WIN32)
	set(CLI_INSTALL_DIR    ".")
	set(BIN_INSTALL_DIR    ".")
	set(PLUGIN_INSTALL_DIR ".")
	set(DATA_INSTALL_DIR   "share")
elseif(APPLE AND WITH_APP_BUNDLE)
	set(CLI_INSTALL_DIR    "/usr/local/bin")
	set(BIN_INSTALL_DIR    ".")
	set(PLUGIN_INSTALL_DIR "openMittsu.app/Contents/PlugIns")
	set(DATA_INSTALL_DIR   "openMittsu.app/Contents/Resources")
else()
	include(GNUInstallDirs)

	set(CLI_INSTALL_DIR    "${CMAKE_INSTALL_BINDIR}")
	set(BIN_INSTALL_DIR    "${CMAKE_INSTALL_BINDIR}")
	set(PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/openmittsu")
	set(DATA_INSTALL_DIR   "${CMAKE_INSTALL_DATADIR}/openmittsu")
endif()

if (OPENMITTSU_DEBUG)
	SET(OPENMITTSU_CONFIG_DEBUG_FLAG_SET ON)
	if (MSVC)
		message(WARNING "Setting the DEBUG flag has no effect on MSVC besides turning on DEBUG logging.")
	endif(MSVC)
	message(STATUS "Configuring OpenMittsu to be build in debug mode.")
else(OPENMITTSU_DEBUG)
	SET(OPENMITTSU_CONFIG_DEBUG_FLAG_SET OFF)
endif(OPENMITTSU_DEBUG)

if (OPENMITTSU_DISABLE_VERSION_UPDATE_CHECK)
	SET(OPENMITTSU_CONFIG_DISABLE_VERSION_UPDATE_CHECK ON)
	message(STATUS "Version update checks on start-up will be disabled.")
else(OPENMITTSU_DISABLE_VERSION_UPDATE_CHECK)
	SET(OPENMITTSU_CONFIG_DISABLE_VERSION_UPDATE_CHECK OFF)
endif(OPENMITTSU_DISABLE_VERSION_UPDATE_CHECK)

# Base path for test files
set(OPENMITTSU_CPP_TESTS_BASE_PATH "${PROJECT_SOURCE_DIR}/test")

# Find the Qt library
set(OPENMITTSU_QT_COMPONENTS "Core Gui Widgets Network Multimedia MultimediaWidgets Sql")
if (APPLE)
	set(OPENMITTSU_QT_COMPONENTS "${OPENMITTSU_QT_COMPONENTS} MacExtras")
endif()

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Gui Widgets Network Multimedia MultimediaWidgets Sql)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets Network Multimedia MultimediaWidgets Sql)

if (NOT WIN32)
	find_package(PkgConfig REQUIRED)
	pkg_check_modules(Libsodium REQUIRED libsodium)
	message(STATUS "Found libsodium via pkgconfig: ${Libsodium_INCLUDE_DIRS}, ${Libsodium_LIBRARIES} and ${Libsodium_LIBRARY_DIRS}")
	if (DEFINED Libsodium_LIBRARY_DIRS)
		link_directories(${Libsodium_LIBRARY_DIRS})
		message(STATUS "Added ${Libsodium_LIBRARY_DIRS} to link directories...")
	endif()
else()
	find_package(Libsodium 1.0.12 REQUIRED)
endif()

find_package(Libqrencode REQUIRED)
find_package(Threads REQUIRED)

if(APPLE)
	set(CMAKE_MACOSX_RPATH TRUE)
	find_program(MACDEPLOYQT_EXE macdeployqt HINTS /usr/local/opt/qt5/bin /usr/local/opt/qt6/bin ENV PATH)
	if(NOT MACDEPLOYQT_EXE)
		message(FATAL_ERROR "macdeployqt is required to build in macOS")
	else()
		message(STATUS "Using macdeployqt: ${MACDEPLOYQT_EXE}")
	endif()
endif()

if (Libsodium_FOUND)
	#message(STATUS "Found LibSodium! ${Libsodium_INCLUDE_DIRS} ${Libsodium_LIBRARIES}")
	# Add LibSodium Includes
	include_directories(${Libsodium_INCLUDE_DIRS})
else ()
	message(SEND_ERROR "Can not build OpenMittsu without LibSodium.")
endif(Libsodium_FOUND)

if (Libqrencode_FOUND)
	message(STATUS "Found LibQREncode with include directory: ${Libqrencode_INCLUDE_DIRS}")
	SET(OPENMITTSU_CONFIG_HAVE_LIBQRENCODE ON)
	# Add libQrEncode Includes
	include_directories(${Libqrencode_INCLUDE_DIRS})
	if (DEFINED Libqrencode_LIBRARY_DIRS)
		link_directories(${Libqrencode_LIBRARY_DIRS})
		message(STATUS "Added ${Libqrencode_LIBRARY_DIRS} to link directories...")
	endif()
else (Libqrencode_FOUND)
	message(STATUS "Could not find LibQREncode, disabling QR Code features.")
	SET(OPENMITTSU_CONFIG_HAVE_LIBQRENCODE OFF)
endif(Libqrencode_FOUND)

# Add base folder for better inclusion paths
include_directories("${PROJECT_SOURCE_DIR}")
include_directories("${PROJECT_SOURCE_DIR}/src")

# Add SpgLog Includes
include_directories("${SPDLOG_MODULE_BASEPATH}/include")

# Force reading files as UTF-8 encoded in MSVC
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")

if(CMAKE_COMPILER_IS_GNUCC)
	set(OPENMITTSU_COMPILED_BY "GCC")
	# Set standard flags for GCC
	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -pedantic")
	set(CMAKE_CXX_STANDARD 17)
	set(CMAKE_CXX_STANDARD_REQUIRED ON)
elseif(MSVC)
	set(OPENMITTSU_COMPILED_BY "MSVC")

	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
	set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")

	add_definitions(/DSODIUM_STATIC)
	add_definitions(/DNOMINMAX)
	add_definitions(/DWIN32_LEAN_AND_MEAN)

	# Disable "C:\Program Files (x86)\Windows Kits\8.1\Include\um\DbgHelp.h(1544): warning C4091: 'typedef ': ignored on left of '' when no variable is declared"
	add_definitions(/wd4091)
	add_definitions(/wd4250)
	# Warns if a switch does not cover all cases
	#add_definitions(/we4061) # Disabled because it blows out in the std library

	# Because Google is not merging the fix
	add_definitions(/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)

	# Enable Multi-Processor Compilation by default
	add_definitions(/MP)
else(CLANG)
	set(OPENMITTSU_COMPILED_BY "Clang (LLVM)")
	# As CLANG is not set as a variable, we need to set it in case we have not matched another compiler.
	set (CLANG ON)
	# Set standard flags for clang
	set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops -O3")
	if(UNIX AND NOT APPLE AND NOT OPENMITTSU_USE_LIBCXX)
		set(CLANG_STDLIB libstdc++)
	else()
		set(CLANG_STDLIB libc++)
		# Set up some Xcode specific settings
		set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++17")
		set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
	endif()
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -stdlib=${CLANG_STDLIB} -Wall -pedantic -Wno-unused-variable -ftemplate-depth=1024")
	set(CMAKE_CXX_STANDARD 17)
	set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()

#
# Make a version file containing the current version from git.
#

# First check if this is a Git checkout or if a custom version tag should be used.
if ((NOT "${OPENMITTSU_CUSTOM_VERSION_STRING}" STREQUAL "") AND (NOT "${OPENMITTSU_CUSTOM_VERSION_STRING}" MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\-[0-9]+\\-[a-z0-9]+(\\-.*)?$"))
	message(FATAL_ERROR "Builtin version information: A custom version string is set, but it is malformed. Should be: 0.1.2-34-567890ab, i.e. major.minor.patch-commitsSinceTag-shortHash")
endif()

set(OPENMITTSU_GIT_VERSION_STRING "")
if (NOT "${OPENMITTSU_CUSTOM_VERSION_STRING}" STREQUAL "")
	message(STATUS "Builtin version information: custom version string set, using ${OPENMITTSU_CUSTOM_VERSION_STRING}")
	set(OPENMITTSU_GIT_VERSION_STRING "${OPENMITTSU_CUSTOM_VERSION_STRING}")
elseif (NOT EXISTS "${PROJECT_SOURCE_DIR}/.git")
	message(STATUS "Builtin version information: .git folder non-existant, falling back to 0.0.0-0-00000000")
	set(OPENMITTSU_GIT_VERSION_STRING "0.0.0-0-00000000")
else()
	message(STATUS "Builtin version information: .git folder exists, using git_describe_checkout")
	include(GetGitRevisionDescription)
	git_describe_checkout(OPENMITTSU_GIT_VERSION_STRING)
endif()

if ("${OPENMITTSU_GIT_VERSION_STRING}" MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\-[0-9]+\\-[a-z0-9]+(\\-.*)?$")
	# Parse the git Tag into variables
	string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" OPENMITTSU_CPP_VERSION_MAJOR "${OPENMITTSU_GIT_VERSION_STRING}")
	string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" OPENMITTSU_CPP_VERSION_MINOR "${OPENMITTSU_GIT_VERSION_STRING}")
	string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" OPENMITTSU_CPP_VERSION_PATCH "${OPENMITTSU_GIT_VERSION_STRING}")
	string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+)\\-.*" "\\1" OPENMITTSU_CPP_VERSION_COMMITS_AHEAD "${OPENMITTSU_GIT_VERSION_STRING}")
	string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.[0-9]+\\-[0-9]+\\-([a-z0-9]+).*" "\\1" OPENMITTSU_CPP_VERSION_HASH "${OPENMITTSU_GIT_VERSION_STRING}")
	string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.[0-9]+\\-[0-9]+\\-[a-z0-9]+\\-(.*)" "\\1" OPENMITTSU_CPP_VERSION_APPENDIX "${OPENMITTSU_GIT_VERSION_STRING}")
	if ("${OPENMITTSU_CPP_VERSION_APPENDIX}" MATCHES "^.*dirty.*$")
		set(OPENMITTSU_CPP_VERSION_DIRTY 1)
	else()
		set(OPENMITTSU_CPP_VERSION_DIRTY 0)
	endif()
message(STATUS "OpenMittsu - Version information: ${OPENMITTSU_CPP_VERSION_MAJOR}.${OPENMITTSU_CPP_VERSION_MINOR}.${OPENMITTSU_CPP_VERSION_PATCH} (${OPENMITTSU_CPP_VERSION_COMMITS_AHEAD} commits ahead of Tag) build from ${OPENMITTSU_CPP_VERSION_HASH} (Dirty: ${OPENMITTSU_CPP_VERSION_DIRTY})")
else()
	message(STATUS "No GIT support, no tags fetched or other problems. Defaulting to version 0.0.0-0-00000000 (result was ${OPENMITTSU_GIT_VERSION_STRING})")
	set(OPENMITTSU_CPP_VERSION_MAJOR 0)
	set(OPENMITTSU_CPP_VERSION_MINOR 0)
	set(OPENMITTSU_CPP_VERSION_PATCH 0)
	set(OPENMITTSU_CPP_VERSION_COMMITS_AHEAD 0)
	set(OPENMITTSU_CPP_VERSION_HASH "00000000")
	set(OPENMITTSU_CPP_VERSION_DIRTY 0)
endif()

# Generate a version string
set(OPENMITTSU_VERSION_NUM "${OPENMITTSU_CPP_VERSION_MAJOR}.${OPENMITTSU_CPP_VERSION_MINOR}.${OPENMITTSU_CPP_VERSION_PATCH}")
set(OPENMITTSU_VERSION "${OPENMITTSU_CPP_VERSION_MAJOR}.${OPENMITTSU_CPP_VERSION_MINOR}.${OPENMITTSU_CPP_VERSION_PATCH}")
if (OPENMITTSU_CPP_VERSION_COMMITS_AHEAD GREATER 0)
	set(OPENMITTSU_VERSION "${OPENMITTSU_VERSION}+${OPENMITTSU_CPP_VERSION_COMMITS_AHEAD}")
endif()
set(OPENMITTSU_VERSION "${OPENMITTSU_VERSION}-${OPENMITTSU_CPP_VERSION_HASH}")

# Check for %zu support
try_run(OPENMITTSU_POINTER_SIZE_TEST_RUN_RESULT OPENMITTSU_POINTER_SIZE_TEST_COMPILE_RESULT "${PROJECT_BINARY_DIR}/testPointerSize" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_ptr_size.cpp" COMPILE_OUTPUT_VARIABLE OPENMITTSU_POINTER_SIZE_TEST_COMPILE_OUTPUT RUN_OUTPUT_VARIABLE OPENMITTSU_POINTER_SIZE_TEST_RUN_OUTPUT)
if (NOT ${OPENMITTSU_POINTER_SIZE_TEST_COMPILE_RESULT})
	message(FATAL_ERROR "Failed to compile pointer size testing program, please contact a developer! Extended Information: ${OPENMITTSU_POINTER_SIZE_TEST_COMPILE_OUTPUT}") 
elseif(${OPENMITTSU_POINTER_SIZE_TEST_RUN_RESULT} LESS 0 OR ${OPENMITTSU_POINTER_SIZE_TEST_RUN_RESULT} GREATER 0)
	message(FATAL_ERROR "Failed to run pointer size testing program, please contact a developer! Extended Information: ${OPENMITTSU_POINTER_SIZE_TEST_RUN_OUTPUT}") 
else()
	set(OPENMITTSU_CPP_POINTER_SIZE "${OPENMITTSU_POINTER_SIZE_TEST_RUN_OUTPUT}")
	message(STATUS "Collected pointer size information (pointer has ${OPENMITTSU_POINTER_SIZE_TEST_RUN_OUTPUT} Bits)")
endif()

# Check for std::make_unique support
try_run(OPENMITTSU_MAKE_UNIQUE_TEST_RUN_RESULT OPENMITTSU_MAKE_UNIQUE_TEST_COMPILE_RESULT "${PROJECT_BINARY_DIR}/testMakeUnique" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_make_unique.cpp" COMPILE_OUTPUT_VARIABLE OPENMITTSU_MAKE_UNIQUE_TEST_COMPILE_OUTPUT RUN_OUTPUT_VARIABLE OPENMITTSU_MAKE_UNIQUE_TEST_RUN_OUTPUT)
if (NOT ${OPENMITTSU_MAKE_UNIQUE_TEST_COMPILE_RESULT})
	set(OPENMITTSU_CONFIG_HAVE_MAKE_UNIQUE OFF)
	message(STATUS "Compiler does NOT support std::make_unique, using replacement. ${OPENMITTSU_MAKE_UNIQUE_TEST_COMPILE_OUTPUT}")
elseif(${OPENMITTSU_MAKE_UNIQUE_TEST_RUN_RESULT} EQUAL 0)
	set(OPENMITTSU_CONFIG_HAVE_MAKE_UNIQUE ON)
	message(STATUS "Compiler does support std::make_unique.")
else()
	set(OPENMITTSU_CONFIG_HAVE_MAKE_UNIQUE OFF)
	message(FATAL_ERROR "Failed to run std::make_unique testing program, please contact a developer! Extended Information: ${OPENMITTSU_MAKE_UNIQUE_TEST_RUN_RESULT} - ${OPENMITTSU_MAKE_UNIQUE_TEST_RUN_OUTPUT}") 
endif()

if (OPENMITTSU_ALLOW_MISSING_QSQLCIPHER)
	SET(OPENMITTSU_CONFIG_ALLOW_MISSING_QSQLCIPHER ON)
else()
	SET(OPENMITTSU_CONFIG_ALLOW_MISSING_QSQLCIPHER OFF)
endif()

# Configure a file to pass the OpenMittsu version to the source code
configure_file (
	"${PROJECT_SOURCE_DIR}/Version.cpp.in"
	"${PROJECT_BINARY_DIR}/include/Version.cpp"
)

# Configure a header file to pass various configuration settings
configure_file (
	"${PROJECT_SOURCE_DIR}/Config.h.in"
	"${PROJECT_BINARY_DIR}/include/Config.h"
)

# Add the binary dir include directory
include_directories("${PROJECT_BINARY_DIR}/include")

##########################################################
#
# Google Testing Framework
#
##########################################################
# In Gentoo Linux, googletest libs are installed as dependency (dev-cpp/gtest)
if (OPENMITTSU_ENABLE_TESTS AND NOT CMAKE_BUILD_TYPE MATCHES "^Gentoo")
	# Download and unpack googletest at configure time
	configure_file("${PROJECT_SOURCE_DIR}/cmake/GoogleTest.cmake.in" googletest-download/CMakeLists.txt)
	execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
	  WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download" )
	execute_process(COMMAND "${CMAKE_COMMAND}" --build .
	  WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download" )

	# Prevent GoogleTest from overriding our compiler/linker options
	# when building with Visual Studio
	set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

	set(BUILD_GMOCK ON)

	# Add googletest directly to our build. This adds
	# the following targets: gtest, gtest_main, gmock
	# and gmock_main
	add_subdirectory("${CMAKE_BINARY_DIR}/googletest-src"
	                 "${CMAKE_BINARY_DIR}/googletest-build" EXCLUDE_FROM_ALL)
endif()

# Main Sources
file(GLOB OPENMITTSU_HEADERS ${PROJECT_SOURCE_DIR}/src/*.h)
file(GLOB OPENMITTSU_SOURCES_CPP ${PROJECT_SOURCE_DIR}/src/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_ACKNOWLEDGMENTS ${PROJECT_SOURCE_DIR}/src/acknowledgments/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_ACKNOWLEDGMENTS ${PROJECT_SOURCE_DIR}/src/acknowledgments/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_BACKUP ${PROJECT_SOURCE_DIR}/src/backup/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_BACKUP ${PROJECT_SOURCE_DIR}/src/backup/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_CPPINTERFACE ${PROJECT_SOURCE_DIR}/src/cpp-interface/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_CPPINTERFACE ${PROJECT_SOURCE_DIR}/src/cpp-interface/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_CRYPTO ${PROJECT_SOURCE_DIR}/src/crypto/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_CRYPTO ${PROJECT_SOURCE_DIR}/src/crypto/*.cpp)

file(GLOB OPENMITTSU_HEADERS_DATABASE_INTERNAL ${PROJECT_SOURCE_DIR}/src/database/internal/*.h)
file(GLOB OPENMITTSU_SOURCES_DATABASE_INTERNAL ${PROJECT_SOURCE_DIR}/src/database/internal/*.cpp)

file(GLOB OPENMITTSU_HEADERS_DATABASE ${PROJECT_SOURCE_DIR}/src/database/*.h)
file(GLOB OPENMITTSU_SOURCES_DATABASE ${PROJECT_SOURCE_DIR}/src/database/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_DATAPROVIDERS ${PROJECT_SOURCE_DIR}/src/dataproviders/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_DATAPROVIDERS ${PROJECT_SOURCE_DIR}/src/dataproviders/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_DATAPROVIDERS_MESSAGES ${PROJECT_SOURCE_DIR}/src/dataproviders/messages/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_DATAPROVIDERS_MESSAGES ${PROJECT_SOURCE_DIR}/src/dataproviders/messages/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_ENCODING ${PROJECT_SOURCE_DIR}/src/encoding/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_ENCODING ${PROJECT_SOURCE_DIR}/src/encoding/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_GENERATED ${PROJECT_BINARY_DIR}/include/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_GENERATED ${PROJECT_BINARY_DIR}/include/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_EXCEPTIONS ${PROJECT_SOURCE_DIR}/src/exceptions/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_EXCEPTIONS ${PROJECT_SOURCE_DIR}/src/exceptions/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_CONTACT_AUDIO ${PROJECT_SOURCE_DIR}/src/messages/contact/audio/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_CONTACT_AUDIO ${PROJECT_SOURCE_DIR}/src/messages/contact/audio/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_CONTACT_FILE ${PROJECT_SOURCE_DIR}/src/messages/contact/file/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_CONTACT_FILE ${PROJECT_SOURCE_DIR}/src/messages/contact/file/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_CONTACT_IMAGE ${PROJECT_SOURCE_DIR}/src/messages/contact/image/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_CONTACT_IMAGE ${PROJECT_SOURCE_DIR}/src/messages/contact/image/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_CONTACT_VIDEO ${PROJECT_SOURCE_DIR}/src/messages/contact/video/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_CONTACT_VIDEO ${PROJECT_SOURCE_DIR}/src/messages/contact/video/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_CONTACT ${PROJECT_SOURCE_DIR}/src/messages/contact/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_CONTACT ${PROJECT_SOURCE_DIR}/src/messages/contact/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_GROUP_AUDIO ${PROJECT_SOURCE_DIR}/src/messages/group/audio/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_GROUP_AUDIO ${PROJECT_SOURCE_DIR}/src/messages/group/audio/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_GROUP_FILE ${PROJECT_SOURCE_DIR}/src/messages/group/file/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_GROUP_FILE ${PROJECT_SOURCE_DIR}/src/messages/group/file/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_GROUP_GROUPPHOTO ${PROJECT_SOURCE_DIR}/src/messages/group/groupphoto/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_GROUP_GROUPPHOTO ${PROJECT_SOURCE_DIR}/src/messages/group/groupphoto/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_GROUP_IMAGE ${PROJECT_SOURCE_DIR}/src/messages/group/image/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_GROUP_IMAGE ${PROJECT_SOURCE_DIR}/src/messages/group/image/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_GROUP_VIDEO ${PROJECT_SOURCE_DIR}/src/messages/group/video/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_GROUP_VIDEO ${PROJECT_SOURCE_DIR}/src/messages/group/video/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES_GROUP ${PROJECT_SOURCE_DIR}/src/messages/group/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES_GROUP ${PROJECT_SOURCE_DIR}/src/messages/group/*.cpp)

file(GLOB OPENMITTSU_HEADERS_MESSAGES ${PROJECT_SOURCE_DIR}/src/messages/*.h)
file(GLOB OPENMITTSU_SOURCES_MESSAGES ${PROJECT_SOURCE_DIR}/src/messages/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_NETWORK ${PROJECT_SOURCE_DIR}/src/network/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_NETWORK ${PROJECT_SOURCE_DIR}/src/network/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_OPTIONS ${PROJECT_SOURCE_DIR}/src/options/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_OPTIONS ${PROJECT_SOURCE_DIR}/src/options/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_PROTOCOL ${PROJECT_SOURCE_DIR}/src/protocol/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_PROTOCOL ${PROJECT_SOURCE_DIR}/src/protocol/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_TASKS ${PROJECT_SOURCE_DIR}/src/tasks/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_TASKS ${PROJECT_SOURCE_DIR}/src/tasks/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_UTILITY ${PROJECT_SOURCE_DIR}/src/utility/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_UTILITY ${PROJECT_SOURCE_DIR}/src/utility/*.cpp)

file(GLOB_RECURSE OPENMITTSU_HEADERS_WIZARDS ${PROJECT_SOURCE_DIR}/src/wizards/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_WIZARDS ${PROJECT_SOURCE_DIR}/src/wizards/*.cpp)
file(GLOB_RECURSE OPENMITTSU_FORMS_WIZARDS ${PROJECT_SOURCE_DIR}/src/wizards/*.ui)

file(GLOB_RECURSE OPENMITTSU_HEADERS_WIDGETS ${PROJECT_SOURCE_DIR}/src/widgets/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_WIDGETS ${PROJECT_SOURCE_DIR}/src/widgets/*.cpp)
file(GLOB_RECURSE OPENMITTSU_FORMS_WIDGETS ${PROJECT_SOURCE_DIR}/src/widgets/*.ui)

file(GLOB_RECURSE OPENMITTSU_HEADERS_WIDGETS_CHAT ${PROJECT_SOURCE_DIR}/src/widgets/chat/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_WIDGETS_CHAT ${PROJECT_SOURCE_DIR}/src/widgets/chat/*.cpp)
file(GLOB_RECURSE OPENMITTSU_FORMS_WIDGETS_CHAT ${PROJECT_SOURCE_DIR}/src/widgets/chat/*.ui)

file(GLOB_RECURSE OPENMITTSU_HEADERS_WIDGETS_PLAYER ${PROJECT_SOURCE_DIR}/src/widgets/player/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_WIDGETS_PLAYER ${PROJECT_SOURCE_DIR}/src/widgets/player/*.cpp)
file(GLOB_RECURSE OPENMITTSU_FORMS_WIDGETS_PLAYER ${PROJECT_SOURCE_DIR}/src/widgets/player/*.ui)

file(GLOB_RECURSE OPENMITTSU_HEADERS_DIALOGS ${PROJECT_SOURCE_DIR}/src/dialogs/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_DIALOGS ${PROJECT_SOURCE_DIR}/src/dialogs/*.cpp)
file(GLOB_RECURSE OPENMITTSU_FORMS_DIALOGS ${PROJECT_SOURCE_DIR}/src/dialogs/*.ui)

file(GLOB_RECURSE OPENMITTSU_HEADERS_UPDATER ${PROJECT_SOURCE_DIR}/src/updater/*.h)
file(GLOB_RECURSE OPENMITTSU_SOURCES_UPDATER ${PROJECT_SOURCE_DIR}/src/updater/*.cpp)
file(GLOB_RECURSE OPENMITTSU_FORMS_UPDATER ${PROJECT_SOURCE_DIR}/src/updater/*.ui)

file(GLOB_RECURSE OPENMITTSU_SOURCES_C ${PROJECT_SOURCE_DIR}/src/*.c)
file(GLOB_RECURSE OPENMITTSU_FORMS ${PROJECT_SOURCE_DIR}/src/*.ui)
file(GLOB_RECURSE OPENMITTSU_RESOURCES ${PROJECT_SOURCE_DIR}/resources/*.qrc)

if ("${QT_VERSION_MAJOR}" STREQUAL "5")
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS ${OPENMITTSU_FORMS})
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS_WIZARDS ${OPENMITTSU_FORMS_WIZARDS})
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS_WIDGETS_CHAT ${OPENMITTSU_FORMS_WIDGETS_CHAT})
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS_WIDGETS_PLAYER ${OPENMITTSU_FORMS_WIDGETS_PLAYER})
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS_WIDGETS ${OPENMITTSU_FORMS_WIDGETS})
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS_DIALOGS ${OPENMITTSU_FORMS_DIALOGS})
	QT5_WRAP_UI(OPENMITTSU_FORMS_HEADERS_UPDATER ${OPENMITTSU_FORMS_UPDATER})
	QT5_ADD_RESOURCES(OPENMITTSU_RESOURCESOURCES ${OPENMITTSU_RESOURCES})
else()
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS ${OPENMITTSU_FORMS})
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS_WIZARDS ${OPENMITTSU_FORMS_WIZARDS})
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS_WIDGETS_CHAT ${OPENMITTSU_FORMS_WIDGETS_CHAT})
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS_WIDGETS_PLAYER ${OPENMITTSU_FORMS_WIDGETS_PLAYER})
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS_WIDGETS ${OPENMITTSU_FORMS_WIDGETS})
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS_DIALOGS ${OPENMITTSU_FORMS_DIALOGS})
	qt_wrap_ui(OPENMITTSU_FORMS_HEADERS_UPDATER ${OPENMITTSU_FORMS_UPDATER})
	qt_add_resources(OPENMITTSU_RESOURCESOURCES ${OPENMITTSU_RESOURCES})
endif()

#set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/widgets/player/QMediaPlaylist_p.h PROPERTY SKIP_AUTOMOC ON)
#set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/widgets/player/QMediaPlaylist.h PROPERTY SKIP_AUTOMOC ON)

# Sources of Build Tools
file(GLOB_RECURSE OPENMITTSU_BUILDTOOLS_VERSIONINFO_HEADERS ${PROJECT_SOURCE_DIR}/buildTools/versionInfo/*.h)
file(GLOB_RECURSE OPENMITTSU_BUILDTOOLS_VERSIONINFO_SOURCES_CPP ${PROJECT_SOURCE_DIR}/buildTools/versionInfo/*.cpp)

# Test Sources
# Note that the tests also need the source files, except for the main file
file(GLOB OPENMITTSU_TEST_MAIN_FILE ${PROJECT_SOURCE_DIR}/test/src/openmittsu-tests.cpp)
file(GLOB_RECURSE OPENMITTSU_TEST_FILES ${PROJECT_SOURCE_DIR}/test/src/*.h ${PROJECT_SOURCE_DIR}/test/src/*.cpp)

function(register_folder_for_grouping name folder)
	string(TOUPPER "${name}" folder_name_upper)
	string(TOLOWER "${name}" folder_name_lower)
	file(GLOB_RECURSE OPENMITTSU_HEADERS_${folder_name_upper} ${PROJECT_SOURCE_DIR}/src/${folder_name_lower}/*.h)
	file(GLOB_RECURSE OPENMITTSU_SOURCES_${folder_name_upper} ${PROJECT_SOURCE_DIR}/src/${folder_name_lower}/*.cpp)
	source_group("${name}" FILES ${OPENMITTSU_HEADERS_${folder_name_upper}} ${OPENMITTSU_SOURCES_${folder_name_upper}})
endfunction(register_folder_for_grouping)

# Main Grouping
source_group(Headers FILES ${OPENMITTSU_HEADERS} ${OPENMITTSU_FORMS_HEADERS} ${OPENMITTSU_HEADERS_GENERATED})
source_group(Sources FILES ${OPENMITTSU_SOURCES_C} ${OPENMITTSU_SOURCES_CPP} ${OPENMITTSU_SOURCES_GENERATED})
source_group(Acknowledgments FILES ${OPENMITTSU_HEADERS_ACKNOWLEDGMENTS} ${OPENMITTSU_SOURCES_ACKNOWLEDGMENTS})
source_group(Backup FILES ${OPENMITTSU_HEADERS_BACKUP} ${OPENMITTSU_SOURCES_BACKUP})
source_group(Cpp-Interface FILES ${OPENMITTSU_HEADERS_CPPINTERFACE} ${OPENMITTSU_SOURCES_CPPINTERFACE})
source_group(Crypto FILES ${OPENMITTSU_HEADERS_CRYPTO} ${OPENMITTSU_SOURCES_CRYPTO})
source_group(Database FILES ${OPENMITTSU_HEADERS_DATABASE} ${OPENMITTSU_SOURCES_DATABASE})
source_group("Database\\Internal" FILES ${OPENMITTSU_HEADERS_DATABASE_INTERNAL} ${OPENMITTSU_SOURCES_DATABASE_INTERNAL})
source_group(DataProviders FILES ${OPENMITTSU_HEADERS_DATAPROVIDERS} ${OPENMITTSU_SOURCES_DATAPROVIDERS})
source_group(DataProviders FILES ${OPENMITTSU_HEADERS_DATAPROVIDERS_MESSAGES} ${OPENMITTSU_SOURCES_DATAPROVIDERS_MESSAGES})
source_group(Encoding FILES ${OPENMITTSU_HEADERS_ENCODING} ${OPENMITTSU_SOURCES_ENCODING})
source_group(Exceptions FILES ${OPENMITTSU_HEADERS_EXCEPTIONS} ${OPENMITTSU_SOURCES_EXCEPTIONS})
source_group(Messages FILES ${OPENMITTSU_HEADERS_MESSAGES} ${OPENMITTSU_SOURCES_MESSAGES})
source_group("Messages\\Contact\\Audio" FILES ${OPENMITTSU_HEADERS_MESSAGES_CONTACT_AUDIO} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_AUDIO})
source_group("Messages\\Contact\\File" FILES ${OPENMITTSU_HEADERS_MESSAGES_CONTACT_FILE} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_FILE})
source_group("Messages\\Contact\\Image" FILES ${OPENMITTSU_HEADERS_MESSAGES_CONTACT_IMAGE} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_IMAGE})
source_group("Messages\\Contact\\Video" FILES ${OPENMITTSU_HEADERS_MESSAGES_CONTACT_VIDEO} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_VIDEO})
source_group("Messages\\Contact" FILES ${OPENMITTSU_HEADERS_MESSAGES_CONTACT} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT})
source_group("Messages\\Group\\Audio" FILES ${OPENMITTSU_HEADERS_MESSAGES_GROUP_AUDIO} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_AUDIO})
source_group("Messages\\Group\\File" FILES ${OPENMITTSU_HEADERS_MESSAGES_GROUP_FILE} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_FILE})
source_group("Messages\\Group\\GroupPhoto" FILES ${OPENMITTSU_HEADERS_MESSAGES_GROUP_GROUPPHOTO} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_GROUPPHOTO})
source_group("Messages\\Group\\Image" FILES ${OPENMITTSU_HEADERS_MESSAGES_GROUP_IMAGE} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_IMAGE})
source_group("Messages\\Group\\Video" FILES ${OPENMITTSU_HEADERS_MESSAGES_GROUP_VIDEO} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_VIDEO})
source_group("Messages\\Group" FILES ${OPENMITTSU_HEADERS_MESSAGES_GROUP} ${OPENMITTSU_SOURCES_MESSAGES_GROUP})
source_group(Network FILES ${OPENMITTSU_HEADERS_NETWORK} ${OPENMITTSU_SOURCES_NETWORK})
source_group(Options FILES ${OPENMITTSU_HEADERS_OPTIONS} ${OPENMITTSU_SOURCES_OPTIONS})
source_group(Protocol FILES ${OPENMITTSU_HEADERS_PROTOCOL} ${OPENMITTSU_SOURCES_PROTOCOL})
source_group(Tasks FILES ${OPENMITTSU_HEADERS_TASKS} ${OPENMITTSU_SOURCES_TASKS})
source_group(Utility FILES ${OPENMITTSU_HEADERS_UTILITY} ${OPENMITTSU_SOURCES_UTILITY})
source_group(Wizards FILES ${OPENMITTSU_HEADERS_WIZARDS} ${OPENMITTSU_SOURCES_WIZARDS} ${OPENMITTSU_FORMS_HEADERS_WIZARDS} ${OPENMITTSU_FORMS_WIZARDS})
source_group("Widgets" FILES ${OPENMITTSU_HEADERS_WIDGETS} ${OPENMITTSU_SOURCES_WIDGETS} ${OPENMITTSU_FORMS_HEADERS_WIDGETS} ${OPENMITTSU_FORMS_WIDGETS})
source_group("Widgets\\Chat" FILES ${OPENMITTSU_HEADERS_WIDGETS_CHAT} ${OPENMITTSU_SOURCES_WIDGETS_CHAT} ${OPENMITTSU_FORMS_HEADERS_WIDGETS_CHAT} ${OPENMITTSU_FORMS_WIDGETS_CHAT})
source_group("Widgets\\Player" FILES ${OPENMITTSU_HEADERS_WIDGETS_PLAYER} ${OPENMITTSU_SOURCES_WIDGETS_PLAYER} ${OPENMITTSU_FORMS_HEADERS_WIDGETS_PLAYER} ${OPENMITTSU_FORMS_WIDGETS_PLAYER})
source_group(Dialogs FILES ${OPENMITTSU_HEADERS_DIALOGS} ${OPENMITTSU_SOURCES_DIALOGS} ${OPENMITTSU_FORMS_HEADERS_DIALOGS} ${OPENMITTSU_FORMS_DIALOGS})
source_group(Updater FILES ${OPENMITTSU_HEADERS_UPDATER} ${OPENMITTSU_SOURCES_UPDATER} ${OPENMITTSU_FORMS_HEADERS_UPDATER} ${OPENMITTSU_FORMS_UPDATER})

# Add the executables
add_library(openMittsuCore STATIC
	${OPENMITTSU_HEADERS_GENERATED} ${OPENMITTSU_SOURCES_GENERATED}
	${OPENMITTSU_HEADERS_ACKNOWLEDGMENTS} ${OPENMITTSU_SOURCES_ACKNOWLEDGMENTS}
	${OPENMITTSU_HEADERS_BACKUP} ${OPENMITTSU_SOURCES_BACKUP}
	${OPENMITTSU_HEADERS_CRYPTO} ${OPENMITTSU_SOURCES_CRYPTO}
	${OPENMITTSU_HEADERS_DATABASE} ${OPENMITTSU_SOURCES_DATABASE}
	${OPENMITTSU_HEADERS_DATABASE_INTERNAL} ${OPENMITTSU_SOURCES_DATABASE_INTERNAL}
	${OPENMITTSU_HEADERS_DATAPROVIDERS} ${OPENMITTSU_SOURCES_DATAPROVIDERS}
	${OPENMITTSU_HEADERS_DATAPROVIDERS_MESSAGES} ${OPENMITTSU_SOURCES_DATAPROVIDERS_MESSAGES}
	${OPENMITTSU_HEADERS_ENCODING} ${OPENMITTSU_SOURCES_ENCODING}
	${OPENMITTSU_HEADERS_EXCEPTIONS} ${OPENMITTSU_SOURCES_EXCEPTIONS}
	${OPENMITTSU_HEADERS_MESSAGES} ${OPENMITTSU_SOURCES_MESSAGES}
	${OPENMITTSU_HEADERS_MESSAGES_CONTACT_AUDIO} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_AUDIO}
	${OPENMITTSU_HEADERS_MESSAGES_CONTACT_FILE} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_FILE}
	${OPENMITTSU_HEADERS_MESSAGES_CONTACT_IMAGE} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_IMAGE}
	${OPENMITTSU_HEADERS_MESSAGES_CONTACT_VIDEO} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT_VIDEO}
	${OPENMITTSU_HEADERS_MESSAGES_CONTACT} ${OPENMITTSU_SOURCES_MESSAGES_CONTACT}
	${OPENMITTSU_HEADERS_MESSAGES_GROUP_AUDIO} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_AUDIO}
	${OPENMITTSU_HEADERS_MESSAGES_GROUP_FILE} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_FILE}
	${OPENMITTSU_HEADERS_MESSAGES_GROUP_GROUPPHOTO} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_GROUPPHOTO}
	${OPENMITTSU_HEADERS_MESSAGES_GROUP_IMAGE} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_IMAGE}
	${OPENMITTSU_HEADERS_MESSAGES_GROUP_VIDEO} ${OPENMITTSU_SOURCES_MESSAGES_GROUP_VIDEO}
	${OPENMITTSU_HEADERS_MESSAGES_GROUP} ${OPENMITTSU_SOURCES_MESSAGES_GROUP}
	${OPENMITTSU_HEADERS_NETWORK} ${OPENMITTSU_SOURCES_NETWORK}
	${OPENMITTSU_HEADERS_OPTIONS} ${OPENMITTSU_SOURCES_OPTIONS}
	${OPENMITTSU_HEADERS_PROTOCOL} ${OPENMITTSU_SOURCES_PROTOCOL}
	${OPENMITTSU_HEADERS_TASKS} ${OPENMITTSU_SOURCES_TASKS}
	${OPENMITTSU_HEADERS_UTILITY} ${OPENMITTSU_SOURCES_UTILITY}
)

set(ICON_RESOURCE_FILE "")
if (WIN32)
	set(ICON_RESOURCE_FILE "${PROJECT_SOURCE_DIR}/resources/icon.rc")
endif()

add_executable(openMittsu ${OPENMITTSU_HEADERS} ${OPENMITTSU_SOURCES_C} ${OPENMITTSU_SOURCES_CPP} ${OPENMITTSU_FORMS_HEADERS} 
	${OPENMITTSU_HEADERS_CPPINTERFACE} ${OPENMITTSU_SOURCES_CPPINTERFACE}
	${OPENMITTSU_FORMS_HEADERS_WIZARDS} ${OPENMITTSU_HEADERS_WIZARDS} ${OPENMITTSU_SOURCES_WIZARDS} 
	${OPENMITTSU_FORMS_HEADERS_WIDGETS} ${OPENMITTSU_HEADERS_WIDGETS} ${OPENMITTSU_SOURCES_WIDGETS}
	${OPENMITTSU_FORMS_HEADERS_WIDGETS_CHAT} ${OPENMITTSU_HEADERS_WIDGETS_CHAT} ${OPENMITTSU_SOURCES_WIDGETS_CHAT}
	${OPENMITTSU_FORMS_HEADERS_WIDGETS_PLAYER} ${OPENMITTSU_HEADERS_WIDGETS_PLAYER} ${OPENMITTSU_SOURCES_WIDGETS_PLAYER}
	${OPENMITTSU_FORMS_HEADERS_DIALOGS} ${OPENMITTSU_HEADERS_DIALOGS} ${OPENMITTSU_SOURCES_DIALOGS} 
	${OPENMITTSU_HEADERS_UPDATER} ${OPENMITTSU_SOURCES_UPDATER} ${OPENMITTSU_FORMS_HEADERS_UPDATER}
	${OPENMITTSU_RESOURCESOURCES} ${ICON_RESOURCE_FILE}
)

add_executable(openMittsuVersionInfo ${OPENMITTSU_BUILDTOOLS_VERSIONINFO_HEADERS} ${OPENMITTSU_BUILDTOOLS_VERSIONINFO_SOURCES_CPP} ${OPENMITTSU_HEADERS_GENERATED} ${OPENMITTSU_SOURCES_GENERATED} ${ICON_RESOURCE_FILE})

if (OPENMITTSU_ENABLE_TESTS)
	add_executable(openMittsuTests ${OPENMITTSU_TEST_MAIN_FILE} ${OPENMITTSU_TEST_FILES}
		${OPENMITTSU_RESOURCESOURCES} ${ICON_RESOURCE_FILE}
	)
endif (OPENMITTSU_ENABLE_TESTS)

if (MSVC)
	set_target_properties(openMittsu PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
endif(MSVC)

# Add target link dependencies
target_link_libraries(openMittsuCore ${Libsodium_LIBRARIES})

if (OPENMITTSU_CONFIG_HAVE_LIBQRENCODE)
	target_link_libraries(openMittsu ${Libqrencode_LIBRARIES})
endif()

if (OPENMITTSU_ENABLE_TESTS AND NOT CMAKE_BUILD_TYPE MATCHES "^Gentoo")
	add_dependencies(openMittsuTests gmock gtest)
endif()

# Use the required modules from Qt 5/Qt 6.
target_link_libraries(openMittsuCore Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::Sql)
target_link_libraries(openMittsu openMittsuCore Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::MultimediaWidgets Qt${QT_VERSION_MAJOR}::Sql)
target_link_libraries(openMittsuVersionInfo Qt${QT_VERSION_MAJOR}::Core)
if (OPENMITTSU_ENABLE_TESTS)
	target_link_libraries(openMittsuTests openMittsuCore Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::MultimediaWidgets Qt${QT_VERSION_MAJOR}::Sql gmock gtest Threads::Threads)
endif (OPENMITTSU_ENABLE_TESTS)

# Link against libc++abi if requested.
if (OPENMITTSU_LINK_LIBCXXABI)
	target_link_libraries(openMittsu "c++abi")
	target_link_libraries(openMittsuCore "c++abi")
	target_link_libraries(openMittsuVersionInfo "c++abi")
	if (OPENMITTSU_ENABLE_TESTS)
		target_link_libraries(openMittsuTests "c++abi")
	endif (OPENMITTSU_ENABLE_TESTS)
endif(OPENMITTSU_LINK_LIBCXXABI)

# Targets, CPACK...
include(InstallRequiredSystemLibraries)

install(TARGETS openMittsu
	RUNTIME
	DESTINATION bin
	COMPONENT OpenMittsu)
install(TARGETS openMittsuVersionInfo
	RUNTIME
	DESTINATION bin
	COMPONENT OpenMittsu)

if (OPENMITTSU_ENABLE_TESTS)
	install(TARGETS openMittsuTests
		RUNTIME
		DESTINATION bin
		COMPONENT OpenMittsu)
endif (OPENMITTSU_ENABLE_TESTS)

# Only available starting from Qt6.3
if (("${QT_VERSION_MAJOR}" STREQUAL "6") AND (DEFINED Qt6Core_FOUND) AND (DEFINED Qt6Core_VERSION) AND (Qt6Core_VERSION VERSION_GREATER 6.3.0))
	message(STATUS "Using Qt6.3+ way of deploying...")
	qt_generate_deploy_app_script(
		TARGET openMittsu
		OUTPUT_SCRIPT deploy_script
		NO_UNSUPPORTED_PLATFORM_ERROR
	)
endif()

if (MSVC)
	# Custom target for packaging.
	if(OPENMITTSU_USE_NSIS)
		set(CPACK_GENERATOR "NSIS")
	else()
		set(CPACK_GENERATOR "ZIP")
	endif()

	set(OPENMITTSU_WINDEPLOYQT_EXE "${Qt${QT_VERSION_MAJOR}Core_DIR}/../../../bin/windeployqt.exe")

	if ("$ENV{VCINSTALLDIR}" STREQUAL "")
		get_filename_component(OPENMITTSU_VCINSTALLDIR "${CMAKE_LINKER}" DIRECTORY)
		file(TO_NATIVE_PATH "${OPENMITTSU_VCINSTALLDIR}/../../" VCINSTALLDIR_NATIVEPATH)

		STRING(REGEX REPLACE "^(.+)\\\\VC\\\\.+" "\\1\\\\VC" VCINSTALLDIR_NATIVEPATH ${VCINSTALLDIR_NATIVEPATH})

		set(ENV{VCINSTALLDIR} "${VCINSTALLDIR_NATIVEPATH}")
	endif()
	add_custom_command(TARGET openMittsu POST_BUILD COMMAND "${CMAKE_SOURCE_DIR}/cmake/callwindeployqt.bat" "${OPENMITTSU_WINDEPLOYQT_EXE}" --dir "${PROJECT_BINARY_DIR}/windeployqt" "$<TARGET_FILE:openMittsu>" "$ENV{VCINSTALLDIR}" COMMENT "Preparing Qt runtime dependencies")
	install(DIRECTORY "${PROJECT_BINARY_DIR}/windeployqt/" DESTINATION bin COMPONENT OpenMittsu)
endif(MSVC)

if (NOT "${OPENMITTSU_ADDITIONAL_INSTALL_FILES}" STREQUAL "")
	foreach(ADD_INST_FILE IN LISTS OPENMITTSU_ADDITIONAL_INSTALL_FILES)
		if(IS_DIRECTORY "${ADD_INST_FILE}")
			message(STATUS "Also installing folder ${ADD_INST_FILE}")
			install(DIRECTORY "${ADD_INST_FILE}/" DESTINATION bin COMPONENT OpenMittsu)
		else()
			message(STATUS "Also installing file ${ADD_INST_FILE}")
			install(FILES "${ADD_INST_FILE}" DESTINATION bin COMPONENT OpenMittsu)
		endif()
	endforeach()
endif()

# CPack
set(CPACK_PACKAGE_NAME "openmittsu")
set(CPACK_PACKAGE_VENDOR "OpenMittsu project team")

set(CPACK_PACKAGE_VERSION_MAJOR "${OPENMITTSU_CPP_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${OPENMITTSU_CPP_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${OPENMITTSU_CPP_VERSION_PATCH}")

if(WIN32)
	set(CPACK_PACKAGE_INSTALL_DIRECTORY "OpenMittsu")
elseif(APPLE AND WITH_APP_BUNDLE)
	set(PROGNAME OpenMittsu)
	configure_file(${CMAKE_SOURCE_DIR}/share/macosx/Info.plist.cmake ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
	set_target_properties(openMittsu PROPERTIES
						MACOSX_BUNDLE ON
						MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)

	if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib")
		install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib"
			DESTINATION "${DATA_INSTALL_DIR}")
	endif()

	set(CPACK_GENERATOR "DragNDrop")
	set(CPACK_DMG_FORMAT "UDBZ")
	set(CPACK_DMG_VOLUME_NAME "openMittsu")
	set(CPACK_SYSTEM_NAME "OSX")
	set(CPACK_STRIP_FILES ON)
	set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${OPENMITTSU_VERSION}")

	add_custom_command(TARGET openMittsu
					 POST_BUILD
					 COMMAND ${MACDEPLOYQT_EXE} openMittsu.app
					 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
					 COMMENT "Deploying app bundle")
endif()

set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT_SOURCE_DIR}/resources/icon-small-for-ico.ico")
set(CPACK_NSIS_HELP_LINK "https://www.openmittsu.de/")
set(CPACK_NSIS_URL_INFO_ABOUT "https://www.openmittsu.de/")
set(CPACK_NSIS_CONTACT "packaging@openmittsu.de")
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
	set(CPACK_NSIS_DISPLAY_NAME "OpenMittsu x64")
else()
	set(CPACK_NSIS_DISPLAY_NAME "OpenMittsu x86")
endif()

set(DISTRO_CODENAME $ENV{DISTRO_CODENAME})
find_program(LSB_RELEASE_CMD lsb_release)
mark_as_advanced(LSB_RELEASE_CMD)
if (LSB_RELEASE_CMD)
	execute_process(COMMAND "${LSB_RELEASE_CMD}" --codename --short
			OUTPUT_VARIABLE DISTRO_CODENAME
			OUTPUT_STRIP_TRAILING_WHITESPACE)
endif ()

# libqrencode4 for everything but stretch
set(LIBQRENCODE_PACKAGE_NAME "libqrencode4")
if ("${DISTRO_CODENAME}" STREQUAL "stretch")
	set(LIBQRENCODE_PACKAGE_NAME "libqrencode3")
endif()

set(CPACK_PACKAGE_VERSION "${OPENMITTSU_CPP_VERSION_MAJOR}.${OPENMITTSU_CPP_VERSION_MINOR}.${OPENMITTSU_CPP_VERSION_PATCH}plus${OPENMITTSU_CPP_VERSION_COMMITS_AHEAD}")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5multimediawidgets5, libqt5multimedia5-plugins, libqt5network5, libqt5sql5, libqt5sql5-sqlite, libqt5sql5-sqlcipher, libqt5widgets5, libsodium23 (>= 1.0.12), ${LIBQRENCODE_PACKAGE_NAME}, gstreamer1.0-libav, libavcodec-extra")
set(CPACK_PACKAGE_CONTACT "Jana Berger <packaging@openmittsu.de>")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Jana Berger <packaging@openmittsu.de>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A chat client for Threema-style chat networks")
set(CPACK_DEBIAN_PACKAGE_SECTION "net")
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "")
set(DEBIAN_PACKAGE_BUILDS_DEPENDS "debhelper (>= 9), cmake (>= 3), qt5-qmake, qtbase5-dev, qtbase5-dev-tools, qtmultimedia5-dev, libsodium-dev, libqrencode-dev, gcc, g++")

if (DISTRO_CODENAME)
	set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}~${DISTRO_CODENAME})
else ()
	message(STATUS "Could not find lsb_release nor is DISTRO_CODENAME set.")
endif ()

find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
if (DPKG_PROGRAM)
	execute_process(COMMAND ${DPKG_PROGRAM} --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
	if (DISTRO_CODENAME)
		set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${OPENMITTSU_CPP_VERSION_MAJOR}.${OPENMITTSU_CPP_VERSION_MINOR}.${OPENMITTSU_CPP_VERSION_PATCH}-${OPENMITTSU_CPP_VERSION_COMMITS_AHEAD}~${DISTRO_CODENAME}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
	else ()
		set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${OPENMITTSU_CPP_VERSION_MAJOR}.${OPENMITTSU_CPP_VERSION_MINOR}.${OPENMITTSU_CPP_VERSION_PATCH}-${OPENMITTSU_CPP_VERSION_COMMITS_AHEAD}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
	endif ()
else (DPKG_PROGRAM)
	if(CMAKE_SIZEOF_VOID_P EQUAL 8)
		set(_ARCHITECTURE "x64")
		SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
	else()
		set(_ARCHITECTURE "x86")
		SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
	endif()
	if(OPENMITTSU_DEBUG)
		set(_EXE_TYPE "Debug")
	else()
		set(_EXE_TYPE "Release")
	endif()
	set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-${OPENMITTSU_CPP_VERSION_HASH}-${CMAKE_SYSTEM_NAME}-${_ARCHITECTURE}-${_EXE_TYPE}")
endif(DPKG_PROGRAM)

SET(CPACK_PACKAGE_EXECUTABLES "openMittsu;OpenMittsu")
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
if (WIN32 AND NOT UNIX)
	SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\openMittsu.exe")
	SET(CPACK_NSIS_DISPLAY_NAME "openMittsu")
	SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.openmittsu.de")
	SET(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\www.openmittsu.de")
	SET(CPACK_NSIS_CONTACT "mail@openmittsu.de")
	SET(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
	if(CMAKE_SIZEOF_VOID_P EQUAL 8)
		SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\bin\\\\vcredist_x64.exe\\\" /install /passive /norestart'")
	else()
		SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\bin\\\\vcredist_x86.exe\\\" /install /passive /norestart'")
	endif()
else(WIN32 AND NOT UNIX)
	SET(CPACK_STRIP_FILES "bin/openMittsu")
	SET(CPACK_SOURCE_STRIP_FILES "")
endif(WIN32 AND NOT UNIX)
set(CPACK_SOURCE_IGNORE_FILES ".git")
set(CPACK_BUNDLE_NAME "openMittsu")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")

set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_ALL OpenMittsu)

INCLUDE(CPack)
