#*******************************************************************************
#**  This file is part of Pecunia.                                           ***
#**                                                                          ***
#**  Copyright (C) 2017, 2018, 2019, 2020, 2021, 2023, 2024, 2025            ***
#**  John Schneiderman <Licencing _AT_ Schneiderman _DOT_ me>                ***
#**                                                                          ***
#**  This program is free software: you can redistribute it and/or modify it ***
#**  under the terms of the GNU Lesser General Public License as published   ***
#**  by the Free Software Foundation, either version 3 of the License, or    ***
#**  (at your option) any later version.                                     ***
#**                                                                          ***
#**  This program is distributed in the hope that it will be useful, but     ***
#**  WITHOUT ANY WARRANTY; without even the implied warranty of              ***
#**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                    ***
#**  See the GNU Lesser General Public License for more details.             ***
#**                                                                          ***
#**  You should have received a copy of the GNU Lesser General Public License***
#**  along with this program. If not, see <http://www.gnu.org/licenses/>.    ***
#*******************************************************************************
project(
	pecunia
	DESCRIPTION ${CMAKE_PROJECT_DESCRIPTION}
	VERSION ${CMAKE_PROJECT_VERSION}
	HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}
	LANGUAGES CXX
)

configure_file(
	"${CMAKE_CURRENT_SOURCE_DIR}/config.hpp.in"
	"${PROJECT_BINARY_DIR}/internal/config.hpp"
)
configure_file(
	"${CMAKE_CURRENT_SOURCE_DIR}/Sizes.hpp.in"
	"${PROJECT_BINARY_DIR}/external/${PROJECT_NAME}/Sizes.hpp"
)
configure_file(
	"${CMAKE_CURRENT_SOURCE_DIR}/SizesInternal.hpp.in"
	"${PROJECT_BINARY_DIR}/internal/Sizes.hpp"
)

set(${PROJECT_NAME}_EXTERNAL_DECLARATIONS
	external/${PROJECT_NAME}/Algorithm.hpp
	external/${PROJECT_NAME}/Conversion.hpp
	external/${PROJECT_NAME}/Currency.hpp
	external/${PROJECT_NAME}/Errors.hpp
	external/${PROJECT_NAME}/Expected.hpp
	external/${PROJECT_NAME}/FloatingPoint.hpp
	external/${PROJECT_NAME}/Information.hpp
	external/${PROJECT_NAME}/Manip.hpp
	external/${PROJECT_NAME}/Math.hpp
	external/${PROJECT_NAME}/Money.hpp
	external/${PROJECT_NAME}/MoneyParts.hpp
	"${PROJECT_BINARY_DIR}/external/${PROJECT_NAME}/${PROJECT_NAME}_export.h"
	external/${PROJECT_NAME}/Rounders.hpp
	external/${PROJECT_NAME}/SetUp.hpp
	"${PROJECT_BINARY_DIR}/external/${PROJECT_NAME}/Sizes.hpp"
	external/${PROJECT_NAME}/Splitter.hpp
)
set(${PROJECT_NAME}_EXTERNAL_DEFINITIONS
	external/${PROJECT_NAME}/Algorithm.cpp
	external/${PROJECT_NAME}/Conversion.cpp
	external/${PROJECT_NAME}/Currency.cpp
	external/${PROJECT_NAME}/Errors.cpp
	external/${PROJECT_NAME}/FloatingPoint.cpp
	external/${PROJECT_NAME}/Information.cpp
	external/${PROJECT_NAME}/Manip.cpp
	external/${PROJECT_NAME}/Math.cpp
	external/${PROJECT_NAME}/Money.cpp
	external/${PROJECT_NAME}/MoneyParts.cpp
	external/${PROJECT_NAME}/Rounders.cpp
	external/${PROJECT_NAME}/SetUp.cpp
	external/${PROJECT_NAME}/Splitter.cpp
)
set(${PROJECT_NAME}_EXTERNAL_TEMPLATE_DEFINITIONS
	external/${PROJECT_NAME}/Algorithm.tpp
	external/${PROJECT_NAME}/Expected.tpp
	external/${PROJECT_NAME}/Math.tpp
)
set(${PROJECT_NAME}_INTERNAL_DECLARATIONS
	internal/Adjustments.hpp
	internal/Attributes.hpp
	internal/BackTrace.hpp
	internal/ManipIndex.hpp
	internal/StreamStateGuard.hpp
	internal/TraceCapture.hpp
	internal/Verification.hpp
	"${PROJECT_BINARY_DIR}/internal/config.hpp"
	"${PROJECT_BINARY_DIR}/internal/Sizes.hpp"
)
set(${PROJECT_NAME}_INTERNAL_DEFINITIONS
	internal/Adjustments.cpp
	internal/ManipIndex.cpp
	internal/StreamStateGuard.cpp
	internal/TraceCapture.cpp
	internal/Verification.cpp
)

if (LINUX)
	message(STATUS "Using GNU/Linux specific source code.")
	set(${PROJECT_NAME}_OS_INTERNAL_DECLARATIONS
	)
	set(${PROJECT_NAME}_OS_INTERNAL_DEFINITIONS
			internal/linux/BackTrace.cpp
	)
elseif (WIN32)
	message(STATUS "Using Microsoft Windows specific source code.")
	set(${PROJECT_NAME}_OS_INTERNAL_DECLARATIONS
		internal/windows/DebugSymbols.hpp
	)
	set(${PROJECT_NAME}_OS_INTERNAL_DEFINITIONS
		internal/windows/BackTrace.cpp
		internal/windows/DebugSymbols.cpp
	)

	if (PROJECT_REVISION)
		set(PROJECT_REVISION_WINDOWS ${PROJECT_REVISION})
	else ()
		set(PROJECT_REVISION_WINDOWS 0)
	endif ()
	configure_file(
		${CMAKE_SOURCE_DIR}/pkg/version.rc.in
		${CMAKE_CURRENT_BINARY_DIR}/version.rc
		@ONLY
	)
	unset(PROJECT_REVISION_WINDOWS)
	list(APPEND ${PROJECT_NAME}_INTERNAL_DEFINITIONS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
elseif (APPLE)
	message(STATUS "Using Apple specific source code.")
	set(${PROJECT_NAME}_OS_INTERNAL_DECLARATIONS
	)
	set(${PROJECT_NAME}_OS_INTERNAL_DEFINITIONS
			internal/macos/BackTrace.cpp
	)
else ()
	message(FATAL_ERROR "OS specific files not specified.")
endif ()

source_group("External Declarations" FILES ${${PROJECT_NAME}_EXTERNAL_DECLARATIONS})
source_group("External Definitions"
	FILES ${${PROJECT_NAME}_EXTERNAL_DEFINITIONS}
		${${PROJECT_NAME}_EXTERNAL_TEMPLATE_DEFINITIONS}
)
source_group("Internal Declarations"
	FILES ${${PROJECT_NAME}_INTERNAL_DECLARATIONS}
		${${PROJECT_NAME}_OS_INTERNAL_DECLARATIONS}
)
source_group("Internal Definitions"
	FILES ${${PROJECT_NAME}_INTERNAL_DEFINITIONS}
		${${PROJECT_NAME}_OS_INTERNAL_DEFINITIONS}
)

add_library(${PROJECT_NAME}
	${${PROJECT_NAME}_EXTERNAL_DECLARATIONS}
	${${PROJECT_NAME}_EXTERNAL_DEFINITIONS}
	${${PROJECT_NAME}_EXTERNAL_TEMPLATE_DEFINITIONS}
	${${PROJECT_NAME}_INTERNAL_DECLARATIONS}
	${${PROJECT_NAME}_INTERNAL_DEFINITIONS}
	${${PROJECT_NAME}_OS_INTERNAL_DECLARATIONS}
	${${PROJECT_NAME}_OS_INTERNAL_DEFINITIONS}
)
target_include_directories(${PROJECT_NAME}
	PUBLIC
		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/external>
	PRIVATE
		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
		$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
		$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/external>
)

if (WIN32)
	message(STATUS "Using Microsoft Windows specific libraries.")
	target_link_libraries(${PROJECT_NAME}
			PUBLIC Dbghelp
	)
	configure_file(
		"${CMAKE_SOURCE_DIR}/src/project.vcxproj.user.in"
		${PROJECT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user @ONLY
	)
	set(ENV{PATH}
		"${CMAKE_BINARY_DIR}/src/$<CONFIG>;$ENV{PATH}"
	)
endif ()

set_target_properties(${PROJECT_NAME} PROPERTIES
		VERSION ${PROJECT_VERSION}
		SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
		LINKER_LANGUAGE CXX
		COMPATIBLE_INTERFACE_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
)

include(GenerateExportHeader)
generate_export_header(${PROJECT_NAME}
		EXPORT_FILE_NAME "${PROJECT_BINARY_DIR}/external/${PROJECT_NAME}/${PROJECT_NAME}_export.h"
)

if (APPLE)
	set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist")
	configure_file(
		"${CMAKE_SOURCE_DIR}/pkg/Info.plist.in"
		"${CMAKE_CURRENT_BINARY_DIR}/Info.plist"
		@ONLY
	)	
	set_target_properties(${PROJECT_NAME} PROPERTIES
		FRAMEWORK TRUE
		MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist"
		XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
	)
	set(CPACK_GENERATOR "DragNDrop")
	set(${PROJECT_NAME}_CMAKE_DIR "CMake/${PROJECT_NAME}")
	set(${PROJECT_NAME}_PUBLIC_INCLUDES_DIR "Frameworks/${PROJECT_NAME}.framework/Headers/${PROJECT_NAME}")
	set(${PROJECT_NAME}_PUBLIC_INCLUDES_IMPORT_DIR "Frameworks/${PROJECT_NAME}.framework/Headers")
	install(
			FILES "${CMAKE_SOURCE_DIR}/pkg/${PROJECT_NAME}.icns"
			DESTINATION Frameworks/${PROJECT_NAME}.framework/Versions/${CMAKE_PROJECT_VERSION}/Resources
			COMPONENT Library
	)
else ()
	set(${PROJECT_NAME}_CMAKE_DIR "${${CMAKE_PROJECT_NAME}_LIBRARY_INSTALL_DIR}/cmake/${PROJECT_NAME}")
	set(${PROJECT_NAME}_PUBLIC_INCLUDES_DIR "include/${PROJECT_NAME}")
	set(${PROJECT_NAME}_PUBLIC_INCLUDES_IMPORT_DIR include)
endif ()

if (BUILD_TESTING)
	add_subdirectory(unit-tests)
endif ()

install(
		TARGETS ${PROJECT_NAME}
		EXPORT ${PROJECT_NAME}Targets
		FRAMEWORK DESTINATION Frameworks COMPONENT Library
		RUNTIME DESTINATION bin COMPONENT Library
		LIBRARY DESTINATION ${${CMAKE_PROJECT_NAME}_LIBRARY_INSTALL_DIR} COMPONENT Library
		ARCHIVE DESTINATION ${${CMAKE_PROJECT_NAME}_LIBRARY_INSTALL_DIR} COMPONENT Devel
    		INCLUDES DESTINATION ${${PROJECT_NAME}_PUBLIC_INCLUDES_IMPORT_DIR}
)
install(
		FILES
			${${PROJECT_NAME}_EXTERNAL_DECLARATIONS}
			${${PROJECT_NAME}_EXTERNAL_TEMPLATE_DEFINITIONS}
		DESTINATION ${${PROJECT_NAME}_PUBLIC_INCLUDES_DIR} COMPONENT Devel
)

if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC AND "${BUILD_SHARED_LIBS}")
	install(
			FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
			DESTINATION bin COMPONENT Debug
	)
endif ()

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
		${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Version.cmake
		VERSION ${PROJECT_VERSION}
		COMPATIBILITY SameMajorVersion
)
configure_package_config_file(${PROJECT_NAME}Config.cmake.in
		"${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake"
		INSTALL_DESTINATION cmake/${PROJECT_NAME}
)
install(
		EXPORT ${PROJECT_NAME}Targets
		FILE ${PROJECT_NAME}Targets.cmake
		DESTINATION ${${PROJECT_NAME}_CMAKE_DIR} COMPONENT Devel
)
install(
		FILES
		${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake
		${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Version.cmake
		DESTINATION ${${PROJECT_NAME}_CMAKE_DIR} COMPONENT Devel
)

if (NOT TARGET uninstall)
	configure_file(
			"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
			"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
			IMMEDIATE @ONLY
	)

	add_custom_target(
			uninstall
			COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
	)
endif ()

set(CMAKE_SKIP_INSTALL_RPATH ON)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/pkg/ReadMe.txt")
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/pkg/${PROJECT_NAME}.png")
set(CPACK_PACKAGE_CHECKSUM SHA256)
set(CPACK_PACKAGE_VENDOR "AureliusSoft")
set(CPACK_PACKAGE_CONTACT "John Schneiderman <packaging@schneiderman.me>")
set(CPACK_THREADS 6)
set(PACKAGE_DESCRIPTION "${CMAKE_PROJECT_NAME} is designed to be an easy and safe to use C++ currency library. It uses\nthe ISO-4217 currency standard for identifying currencies, and has a fixed\nmonetary size for efficient mathematical performance.")
set(CPACK_COMPONENT_Development_DEPENDS Library)
set(CPACK_COMPONENT_Debug_DEPENDS Library)

if (APPLE)
	set(CPACK_STRIP_FILES OFF)
else ()
	set(CPACK_STRIP_FILES ON)
endif ()
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${PROJECT_SEMANTIC_VERSION}-${CMAKE_SYSTEM_PROCESSOR}")

if (LINUX)
	install(
			FILES "${CMAKE_SOURCE_DIR}/pkg/${PROJECT_NAME}.png"
			DESTINATION share/pixmaps
			COMPONENT Library
	)
	set(CPACK_RPM_PACKAGE_DESCRIPTION "${PACKAGE_DESCRIPTION}")
	set(CPACK_RPM_PACKAGE_GROUP "Development/C++")
	set(CPACK_RPM_PACKAGE_LICENSE "LGPL-3.0-or-later")
	set(CPACK_RPM_COMPONENT_INSTALL ON)
	set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
	set(CPACK_RPM_PACKAGE_AUTOREQPROV ON)
	set(CPACK_RPM_CHANGELOG_FILE "${CMAKE_SOURCE_DIR}/ChangeLog")
	set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/debug")
	set(CPACK_RPM_SPEC_MORE_DEFINE "%define _build_id_links none")
	set(CPACK_RPM_Library_DEBUGINFO_PACKAGE ON)
	set(CPACK_RPM_Development_PACKAGE_REQUIRES "${PROJECT_NAME}-Runtime")
	set(CPACK_RPM_Development_PACKAGE_ARCHITECTURE "noarch")

	set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${PACKAGE_DESCRIPTION}")
	set(CPACK_DEBIAN_PACKAGE_SECTION "libs")
	set(CPACK_DEB_COMPONENT_INSTALL ON)
	set(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS ON)
	set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
	set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
	set(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS ON)
	set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
	set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
	set(CPACK_DEBIAN_PACKAGE_DEPENDS "${PROJECT_NAME}-runtime (= ${PROJECT_VERSION})")
	set(CPACK_DEBIAN_Development_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}")
	set(CPACK_DEBIAN_Development_PACKAGE_ARCHITECTURE "all")
elseif (WIN32)
	install(
		FILES "${CMAKE_SOURCE_DIR}/pkg/${PROJECT_NAME}.ico"
		DESTINATION bin
		COMPONENT Library
	)
	set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}")
	set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/pkg\\\\${PROJECT_NAME}.ico")
	set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/pkg\\\\${PROJECT_NAME}.ico")
endif ()
include(CPack)

#{ Set-up package dependencies

cpack_add_component_group(Runtime
		DISPLAY_NAME "Runtime Files"
		DESCRIPTION "All files needed to run the library ${CMAKE_PROJECT_NAME}."
		EXPANDED
)
cpack_add_component_group(Development
		DISPLAY_NAME "Development Files"
		DESCRIPTION "All files supporting development with ${CMAKE_PROJECT_NAME}."
)
cpack_add_component(Library
		DISPLAY_NAME "C++ Libraries"
		DESCRIPTION "${PACKAGE_DESCRIPTION}"
		REQUIRED
		GROUP Runtime
)
cpack_add_component(Devel
		DISPLAY_NAME "C++ Headers"
		DESCRIPTION "All the development header files for C++. Also, provides the files for\nusing CMake."
		DEPENDS Library
		DISABLED
		GROUP Development
)
cpack_add_component(Debug
		DISPLAY_NAME "Debug Symbols"
		DESCRIPTION "Files needed for debugging and, on Windows, generating stack-traces."
		DEPENDS Library
		DISABLED
		GROUP Development
)

#}

add_subdirectory(gen-codes)
