# SPDX-License-Identifier: BSD-2-Clause

# Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:

# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

cmake_minimum_required(VERSION 3.23)

cmake_policy(SET CMP0135 NEW)

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

# set the project name
project(
    libcifpp
    VERSION 10.0.3
    LANGUAGES CXX C)

list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(FindAtomic)
include(CMakePackageConfigHelpers)
include(GenerateExportHeader)
include(CTest)
include(ExternalProject)
include(FetchContent)
include(VersionString)

# When building with ninja-multiconfig, build both debug and release by default
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
    set(CMAKE_CROSS_CONFIGS "Debug;Release")
    set(CMAKE_DEFAULT_CONFIGS "Debug;Release")
endif()

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    set(CMAKE_CXX_FLAGS
        "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers"
    )
elseif(MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()

# Build documentation?
set(BUILD_DOCUMENTATION OFF CACHE BOOL "Build the documentation")

# Build examples?
set(BUILD_EXAMPLES ON CACHE BOOL "Build the example applications")

# Optionally build a version to be installed inside CCP4
set(BUILD_FOR_CCP4 OFF CACHE BOOL "Build a version to be installed in CCP4")

# Create the cql/sqlite interface
set(BUILD_SQLITE_INTERFACE ON CACHE BOOL "Build the sqlite interface")

# Building shared libraries?
if(NOT (BUILD_FOR_CCP4 AND WIN32))
    set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build a shared library instead of a static one")
endif()

if(PROJECT_IS_TOP_LEVEL AND NOT BUILD_FOR_CCP4)
    # Lots of code depend on the availability of the components.cif file
    set(CIFPP_DOWNLOAD_CCD ON CACHE BOOL "Download the CCD file components.cif during installation")

    # An optional cron script can be installed to keep the data files up-to-date
    if(UNIX AND NOT APPLE)
        set(CIFPP_INSTALL_UPDATE_SCRIPT ON CACHE BOOL "Install the script to update CCD and dictionary files")
    endif()
else()
    unset(CIFPP_DOWNLOAD_CCD)
    unset(CIFPP_INSTALL_UPDATE_SCRIPT)
endif()

# When CCP4 is sourced in the environment, we can recreate the symmetry
# operations table
if(EXISTS "$ENV{CCP4}/lib/data/syminfo.lib")
    set(CIFPP_RECREATE_SYMOP_DATA ON CACHE BOOL "Recreate SymOp data table in case it is out of date")
endif()

# CCP4 build
if(BUILD_FOR_CCP4)
    if("$ENV{CCP4}" STREQUAL "" OR NOT EXISTS $ENV{CCP4})
        message(FATAL_ERROR "cifpp: A CCP4 built was requested but CCP4 was not sourced")
    else()
        list(PREPEND CMAKE_MODULE_PATH "$ENV{CCP4}")
        list(PREPEND CMAKE_PREFIX_PATH "$ENV{CCP4}")
        set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}")

        if(WIN32)
            set(BUILD_SHARED_LIBS ON)
        endif()
    endif()
endif()

# Now include the GNUInstallDirs module
include(GNUInstallDirs)

if(WIN32)
    if(${CMAKE_SYSTEM_VERSION} GREATER_EQUAL 10) # Windows 10
        add_definitions(-D _WIN32_WINNT=0x0A00)
    elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.3) # Windows 8.1
        add_definitions(-D _WIN32_WINNT=0x0603)
    elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.2) # Windows 8
        add_definitions(-D _WIN32_WINNT=0x0602)
    elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.1) # Windows 7
        add_definitions(-D _WIN32_WINNT=0x0601)
    elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.0) # Windows Vista
        add_definitions(-D _WIN32_WINNT=0x0600)
    else() # Windows XP (5.1)
        add_definitions(-D _WIN32_WINNT=0x0501)
    endif()

    # We do not want to write an export file for all our symbols...
    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()

if(MSVC)
    # make msvc standards compliant...
    add_compile_options(/permissive- /bigobj)
    add_link_options(/NODEFAULTLIB:library)
endif()

# Libraries

if(MSVC)
    # Avoid linking the shared library of zlib. Search ZLIB_ROOT first if it is
    # set.
    if(ZLIB_ROOT)
        set(_ZLIB_SEARCH_ROOT PATHS ${ZLIB_ROOT} NO_DEFAULT_PATH)
        list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT)
    endif()

    # Normal search.
    set(_ZLIB_x86 "(x86)")
    set(_ZLIB_SEARCH_NORMAL
        PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]"
        "$ENV{ProgramFiles}/zlib" "$ENV{ProgramFiles${_ZLIB_x86}}/zlib")
    unset(_ZLIB_x86)
    list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL)

    if(BUILD_FOR_CCP4)
        list(PREPEND _ZLIB_SEARCHES "$ENV{CCP4}/lib")
    endif()

    foreach(search ${_ZLIB_SEARCHES})
        find_library(
            ZLIB_LIBRARY
            NAMES zlibstatic NAMES_PER_DIR ${${search}}
            PATH_SUFFIXES lib)
    endforeach()
endif()

# Using fast_float for float parsing, but only if needed
try_compile(STD_CHARCONV_COMPILING
    SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-charconv.cpp
    CXX_STANDARD 20
    CXX_STANDARD_REQUIRED ON)

if(NOT STD_CHARCONV_COMPILING)
    message(NOTICE "libcifpp: Using fast_float for std::from_chars")
    find_package(FastFloat 8.0 REQUIRED CONFIG)
endif()

find_package(Threads)
find_package(ZLIB QUIET)

if(NOT ZLIB_FOUND)
    message(FATAL_ERROR "cifpp: The zlib development files were not found you this system, please install them and try again (hint: on debian/ubuntu use apt-get install zlib1g-dev)")
endif()

include(FindPkgConfig)

if(PKG_CONFIG_FOUND)
    pkg_check_modules(PCRE2 IMPORTED_TARGET libpcre2-8)
endif()

if(NOT PCRE2_FOUND)
    add_subdirectory(pcre2-simple)
endif()

# Using Eigen3 is a bit of a thing. We don't want to build it completely since
# we only need a couple of header files. Nothing special. But often, eigen3 is
# already installed and then we prefer that.
find_package(Eigen3 3.4 QUIET)

if(Eigen3_FOUND AND TARGET Eigen3::Eigen)
    get_target_property(EIGEN_INCLUDE_DIR Eigen3::Eigen
        INTERFACE_INCLUDE_DIRECTORIES)
else()
    # Use ExternalProject since FetchContent always tries to install the result...
    ExternalProject_Add(my-eigen3
        URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.zip
        DOWNLOAD_EXTRACT_TIMESTAMP TRUE
        CONFIGURE_COMMAND ""
        BUILD_COMMAND ""
        INSTALL_COMMAND "")

    ExternalProject_Get_Property(my-eigen3 SOURCE_DIR)
    set(EIGEN_INCLUDE_DIR ${SOURCE_DIR})
endif()

# SymOp data table
if(CIFPP_RECREATE_SYMOP_DATA)
    # The tool to create the table
    add_executable(symop-map-generator
        "${CMAKE_CURRENT_SOURCE_DIR}/src/symop-map-generator.cpp")

    target_compile_features(symop-map-generator PUBLIC cxx_std_20)

    add_custom_command(
        OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
        COMMAND
        $<TARGET_FILE:symop-map-generator> $ENV{CLIBD}/syminfo.lib
        $ENV{CLIBD}/symop.lib ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp)

    add_custom_target(
        OUTPUT
        ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
        DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib"
        "$ENV{CLIBD}/symop.lib")
endif()

# Create a revision file, containing the current git version info
write_version_header("${CMAKE_CURRENT_SOURCE_DIR}/src/" LIB_NAME "LibCIFPP")

add_library(cifpp)
add_library(cifpp::cifpp ALIAS cifpp)

# Sources
list(APPEND project_sources
    ${CMAKE_CURRENT_SOURCE_DIR}/src/category.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/condition.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/datablock.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/dictionary_parser.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/file.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/item.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/parser.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/row.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/validate.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/text.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/utilities.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/atom_type.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/compound.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/point.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/symmetry.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/model.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/cif2pdb.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb_record.hpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.hpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/reconstruct.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/validate-pdbx.cpp
)

list(APPEND project_headers
    include/cif++.hpp
    include/cif++/cif++.hpp
    include/cif++/atom_type.hpp
    include/cif++/category.hpp
    include/cif++/compound.hpp
    include/cif++/condition.hpp
    include/cif++/datablock.hpp
    include/cif++/dictionary_parser.hpp
    include/cif++/exports.hpp
    include/cif++/file.hpp
    include/cif++/format.hpp
    include/cif++/gzio.hpp
    include/cif++/item.hpp
    include/cif++/iterator.hpp
    include/cif++/matrix.hpp
    include/cif++/model.hpp
    include/cif++/parser.hpp
    include/cif++/pdb.hpp
    include/cif++/point.hpp
    include/cif++/row.hpp
    include/cif++/symmetry.hpp
    include/cif++/text.hpp
    include/cif++/utilities.hpp
    include/cif++/validate.hpp
)

if(BUILD_SQLITE_INTERFACE)
    find_package(SQLite3 QUIET)
    if(SQLite3_FOUND)
        target_link_libraries(cifpp PRIVATE SQLite::SQLite3)
    else()
        FetchContent_Populate(SQLite3
            URL https://sqlite.org/2025/sqlite-amalgamation-3510100.zip
            URL_HASH SHA3_256=856b52ffe7383d779bb86a0ed1ddc19c41b0e5751fa14ce6312f27534e629b64
            EXCLUDE_FROM_ALL)

        list(APPEND project_sources $<BUILD_INTERFACE:${sqlite3_SOURCE_DIR}>/sqlite3.c)
        target_include_directories(cifpp PRIVATE $<BUILD_INTERFACE:${sqlite3_SOURCE_DIR}>)
    endif()

    list(APPEND project_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/cql.cpp)
    list(APPEND project_headers include/cif++/cql.hpp)
endif()

if(TARGET my-eigen3)
    add_dependencies(cifpp my-eigen3)
endif()

target_sources(cifpp
    PRIVATE ${project_sources}
    ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
    PUBLIC
    FILE_SET cifpp_headers TYPE HEADERS
    BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
    FILES ${project_headers}
)

# The code now really requires C++20
target_compile_features(cifpp PUBLIC cxx_std_23)

generate_export_header(cifpp EXPORT_FILE_NAME
    ${CMAKE_CURRENT_SOURCE_DIR}/include/cif++/exports.hpp)

if(MSVC)
    target_compile_definitions(cifpp PUBLIC NOMINMAX=1)
endif()

set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)

target_include_directories(
    cifpp
    PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
    PRIVATE "${EIGEN_INCLUDE_DIR}")

target_link_libraries(cifpp
    PUBLIC Threads::Threads ZLIB::ZLIB $<$<TARGET_EXISTS:std::atomic>:std::atomic>)

if(PCRE2_FOUND)
    target_include_directories(cifpp PRIVATE ${PCRE2_INCLUDE_DIRS})
    target_link_libraries(cifpp PRIVATE ${PCRE2_LINK_LIBRARIES})
else()
    target_link_libraries(cifpp PRIVATE $<BUILD_INTERFACE:pcre2s>)
endif()

if(NOT STD_CHARCONV_COMPILING)
    get_target_property(FF_INC_DIR FastFloat::fast_float INTERFACE_INCLUDE_DIRECTORIES)
    target_include_directories(cifpp PRIVATE ${FF_INC_DIR})
	target_compile_definitions(cifpp PRIVATE USE_FAST_FLOAT)
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
    target_link_options(cifpp PRIVATE -undefined dynamic_lookup)
endif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")

if(CIFPP_DOWNLOAD_CCD)
    # download the components.cif file from CCD
    set(COMPONENTS_CIF ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/components.cif)

    if(EXISTS ${COMPONENTS_CIF})
        file(SIZE ${COMPONENTS_CIF} CCD_FILE_SIZE)

        if(CCD_FILE_SIZE EQUAL 0)
            message(STATUS "cifpp: Removing empty ${COMPONENTS_CIF} file")
            file(REMOVE "${COMPONENTS_CIF}")
        endif()
    endif()

    if(NOT EXISTS ${COMPONENTS_CIF})
        # Since the file(DOWNLOAD) command in cmake does not use compression, we try
        # to download the gzipped version and decompress it ourselves.
        find_program(GUNZIP gunzip)

        if(WIN32 OR GUNZIP STREQUAL "GUNZIP-NOTFOUND")
            file(
                DOWNLOAD https://files.wwpdb.org/pub/pdb/data/monomers/components.cif
                ${COMPONENTS_CIF}
                SHOW_PROGRESS
                STATUS CCD_FETCH_STATUS)
        else()
            if(NOT EXISTS "${COMPONENTS_CIF}.gz")
                file(
                    DOWNLOAD
                    https://files.wwpdb.org/pub/pdb/data/monomers/components.cif.gz
                    ${COMPONENTS_CIF}.gz
                    SHOW_PROGRESS
                    STATUS CCD_FETCH_STATUS)
            endif()

            add_custom_command(
                OUTPUT ${COMPONENTS_CIF}
                COMMAND "${GUNZIP}" ${COMPONENTS_CIF}.gz
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/)

            add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF})
        endif()

        # Do not continue if downloading went wrong
        list(POP_FRONT CCD_FETCH_STATUS CCD_FETCH_STATUS_CODE)

        if(CCD_FETCH_STATUS_CODE)
            message(
                FATAL_ERROR "cifpp: Error trying to download CCD file: ${CCD_FETCH_STATUS}")
        endif()
    endif()
endif()

# Installation directories
if(BUILD_FOR_CCP4)
    set(CIFPP_DATA_DIR
        "$ENV{CCP4}/share/libcifpp"
        CACHE PATH "Directory where dictionary and other static data is stored")
else()
    set(CIFPP_DATA_DIR
        "${CMAKE_INSTALL_FULL_DATADIR}/libcifpp"
        CACHE PATH "Directory where dictionary and other static data is stored")
endif()

if(CIFPP_DATA_DIR)
    target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}")
    set_target_properties(cifpp PROPERTIES CIFPP_DATA_DIR ${CIFPP_DATA_DIR})
endif()

if(NOT PROJECT_IS_TOP_LEVEL)
    set(CIFPP_SHARE_DIR ${CIFPP_DATA_DIR} PARENT_SCOPE)
endif()

if(UNIX AND NOT BUILD_FOR_CCP4)
    if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local")
        set(CIFPP_CACHE_DIR
            "/var/cache/libcifpp"
            CACHE PATH "The directory where downloaded data files are stored")
    else()
        set(CIFPP_CACHE_DIR
            "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/cache/libcifpp"
            CACHE PATH "The directory where downloaded data files are stored")
    endif()

    target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")

    set(CIFPP_ETC_DIR
        "${CMAKE_INSTALL_FULL_SYSCONFDIR}"
        CACHE PATH "The directory where the update configuration file is stored")
else()
    unset(CIFPP_CACHE_DIR)
endif()

# Install rules
install(TARGETS cifpp
    EXPORT cifpp
    FILE_SET cifpp_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

if(MSVC AND BUILD_SHARED_LIBS)
    install(
        FILES $<TARGET_PDB_FILE:cifpp>
        DESTINATION ${CMAKE_INSTALL_LIBDIR}
        OPTIONAL)
endif()

# Clean up old config files (with old names)
file(GLOB OLD_CONFIG_FILES
    ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cifpp/cifppConfig*.cmake
    ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cifpp/cifppTargets*.cmake)

if(OLD_CONFIG_FILES)
    message(
        STATUS "cifpp: Installation will remove old config files: ${OLD_CONFIG_FILES}")
    install(CODE "file(REMOVE ${OLD_CONFIG_FILES})")
endif()

install(EXPORT cifpp
    NAMESPACE cifpp::
    FILE "cifpp-targets.cmake"
    DESTINATION lib/cmake/cifpp)

install(
    FILES ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
    ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
    ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ma.dic
    DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp)

if(CIFPP_DATA_DIR AND CIFPP_DOWNLOAD_CCD)
    install(FILES ${COMPONENTS_CIF}
        DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp)
endif()

set(CONFIG_TEMPLATE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cifpp-config.cmake.in)

configure_package_config_file(
    ${CONFIG_TEMPLATE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake
    INSTALL_DESTINATION lib/cmake/cifpp
    PATH_VARS CIFPP_DATA_DIR)

install(
    FILES "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake"
    DESTINATION lib/cmake/cifpp)

set_target_properties(
    cifpp
    PROPERTIES VERSION ${PROJECT_VERSION}
    SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
    INTERFACE_cifpp_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})

set_property(
    TARGET cifpp
    APPEND
    PROPERTY COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION)

write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake"
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY AnyNewerVersion)

if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL)
    add_subdirectory(test)
endif()

# Optionally install the update scripts for CCD and dictionary files
if(CIFPP_INSTALL_UPDATE_SCRIPT)
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tools/update-libcifpp-data.in
        update-libcifpp-data @ONLY)

    if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
        ${CMAKE_SYSTEM_NAME} STREQUAL "GNU" OR
        ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
        install(
            FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
            DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cron.weekly
            PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE
            WORLD_READ)
    else()
        message(FATAL_ERROR "cifpp: Don't know where to install the update script")
    endif()

    # a config file, to make it complete
    # install(DIRECTORY DESTINATION "${CMAKE_INSTALL_LOCALSTATEDIR}/libcifpp")
    if(NOT EXISTS "${CMAKE_INSTALL_SYSCONFDIR}/libcifpp.conf")
        file(
            WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf
            [[# Uncomment the next line to enable automatic updates
# update=true
]])
        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf
            DESTINATION ${CMAKE_INSTALL_SYSCONFDIR})
        install(
            CODE "message(\"cifpp: A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")"
        )

        install(DIRECTORY DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/libcifpp/cache-update.d)
    endif()

    target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
endif()

if(BUILD_DOCUMENTATION)
    add_subdirectory(docs)
endif()

if(BUILD_EXAMPLES)
    add_subdirectory(examples)
endif()
