#  Copyright (C) 2026 ChiPass Team <contact@chipass.org>
#  Copyright (C) 2023 KeePassXC Team <team@keepassxc.org>
#  Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 2 or (at your option)
#  version 3 of the License.
#
#  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 General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

# Configuration headers
#
if (CHIPASS_BUILD_TYPE STREQUAL Release)
  set(CHIPASS_BUILD_TYPE_RELEASE YES)
elseif (CHIPASS_BUILD_TYPE STREQUAL Snapshot)
  set(CHIPASS_BUILD_TYPE_SNAPSHOT YES)
endif()

if (CHIPASS_DIST_TYPE STREQUAL Flatpak)
  set(CHIPASS_DIST_TYPE_FLATPAK YES)
elseif (CHIPASS_DIST_TYPE STREQUAL AppBundle)
  set(CHIPASS_DIST_TYPE_APP_BUNDLE YES)
endif()

if (CMAKE_BUILD_TYPE STREQUAL Sanitize)
  if (memory IN_LIST CHIPASS_SANITIZE)
    set(CHIPASS_SANITIZE_MEMORY YES)
  endif()
  if (address IN_LIST CHIPASS_SANITIZE)
    set(CHIPASS_SANITIZE_ADDRESS YES)
  endif()
  if (leak IN_LIST CHIPASS_SANITIZE)
    set(CHIPASS_SANITIZE_LEAK YES)
  endif()
endif()

configure_file(app-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/app-config.h)
configure_file(app-version.h.in ${CMAKE_CURRENT_BINARY_DIR}/app-version.h)

# Library dependencies
#
# Due to extensive interdependencies betwen components, the dependency graph looks like this:
#
# {Qt, botan, ...} ← ChiPass_common ← {ChiPass_keys, ChiPass_gui, ...} ← ChiPass_all ← {ChiPass, ChiPass_cli}
#
# The `ChiPass_common` library aggregates the upstream dependencies and any common build flags, while
# the `ChiPass_all` library aggregates all of the application components shared between CLI and GUI interfaces.
#
add_library(ChiPass_common INTERFACE)

target_include_directories(ChiPass_common INTERFACE
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_BINARY_DIR}
)

target_link_libraries(ChiPass_common INTERFACE
  PkgConfig::botan
  PkgConfig::libargon2
  PkgConfig::libqrencode
  PkgConfig::minizip
  $<TARGET_NAME_IF_EXISTS:PkgConfig::readline>
  PkgConfig::zlib
  Qt6::Core
  Qt6::Core5Compat
  Qt6::Concurrent
  Qt6::Gui
  Qt6::Network
  Qt6::SvgWidgets
  Qt6::Widgets
  zxcvbn
)

if (CHIPASS_ENABLE_YUBIKEY)
  if (UNIX AND NOT APPLE)
    target_link_libraries(ChiPass_common INTERFACE PkgConfig::pcsclite)
  elseif (APPLE)
    target_link_libraries(ChiPass_common INTERFACE PCSC::PCSC)
  elseif (WIN32)
    target_link_libraries(ChiPass_common INTERFACE winscard)
  endif()
  target_link_libraries(ChiPass_common INTERFACE ykcore)
endif()

if (APPLE)
  target_link_libraries(ChiPass_common INTERFACE
    $<LINK_LIBRARY:FRAMEWORK,Foundation>
    $<LINK_LIBRARY:FRAMEWORK,AppKit>
    $<LINK_LIBRARY:FRAMEWORK,Carbon>
    $<LINK_LIBRARY:FRAMEWORK,Security>
    $<LINK_LIBRARY:FRAMEWORK,LocalAuthentication>
    $<LINK_LIBRARY:FRAMEWORK,ScreenCaptureKit>
  )
elseif (FREEDESKTOP)
  target_link_libraries(ChiPass_common INTERFACE
    PkgConfig::libusb
    Qt6::DBus
    Qt6::GuiPrivate

    $<$<BOOL:${CHIPASS_ENABLE_DESKTOP_X11}>:X11::X11>
    $<$<BOOL:${CHIPASS_ENABLE_DESKTOP_X11}>:X11::Xtst>
  )
elseif (WIN32)
  target_link_libraries(ChiPass_common INTERFACE
    Qt6::GuiPrivate

    ws2_32
    wtsapi32
  )

  if (MSVC)
    # Used for WindowsHello.
    target_link_libraries(ChiPass_common INTERFACE
      WindowsApp
    )
  endif()
endif()


# Application components
#
add_library(ChiPass_all STATIC)

function (chipass_add_component name)
  add_library(ChiPass_${name} OBJECT)
  target_link_libraries(ChiPass_${name} PUBLIC ChiPass_common)
  target_link_libraries(ChiPass_all PUBLIC ChiPass_${name})
endfunction()

function (chipass_add_executable name type)
  add_executable(${name} ${ARGN})

  if (WIN32)
    set(VERSION_EXECUTABLE_NAME "${name}.exe")
    string(TIMESTAMP VERSION_COPYRIGHT_YEAR "%Y")
    configure_file(
      ${CMAKE_SOURCE_DIR}/src/version-info.rc.in
      ${CMAKE_CURRENT_BINARY_DIR}/${name}.version-info.rc
    )
    target_sources(${name} PRIVATE
      ${CMAKE_SOURCE_DIR}/share/windows/icon.rc
      ${CMAKE_CURRENT_BINARY_DIR}/${name}.version-info.rc
    )
  endif()

  if (type STREQUAL CLI)
    install(TARGETS ${name}
      RUNTIME DESTINATION ${CHIPASS_INSTALL_BINDIR} COMPONENT Runtime
    )
  elseif (type STREQUAL GUI)
    set_target_properties(${name} PROPERTIES
      WIN32_EXECUTABLE TRUE
    )
    if (CHIPASS_DIST_TYPE_APP_BUNDLE)
      configure_file(${CMAKE_SOURCE_DIR}/share/macosx/Info.plist.in Info.plist)
      set_target_properties(${name} PROPERTIES
        MACOSX_BUNDLE TRUE
        MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
      )
    endif()

    install(TARGETS ${name}
      RUNTIME DESTINATION ${CHIPASS_INSTALL_BINDIR} COMPONENT Runtime
      BUNDLE DESTINATION . COMPONENT Runtime # (ignored unless building a bundle)
    )
  endif()
endfunction()

add_subdirectory(autotype)
add_subdirectory(browser)
add_subdirectory(core)
add_subdirectory(crypto)
add_subdirectory(fdosecrets)
add_subdirectory(format)
add_subdirectory(keeshare)
add_subdirectory(keys)
add_subdirectory(qrcode)
add_subdirectory(sshagent)
add_subdirectory(streams)
add_subdirectory(gui)
add_subdirectory(cli)
add_subdirectory(proxy)


# Application message localization
#
file(GLOB ts_files ${CMAKE_SOURCE_DIR}/share/translations/*.ts)
list(FILTER ts_files EXCLUDE REGEX [=[ChiPass_en.ts$]=]) # exclude the template file
qt6_add_lupdate(ChiPass
  SOURCE_TARGETS ChiPass_all
  TS_FILES ${ts_files}
)
qt6_add_lrelease(ChiPass
  TS_FILES ${ts_files}
  QM_FILES_OUTPUT_VARIABLE qm_files
)
qt6_add_resources(ChiPass_all "i18n_ChiPass"
  PREFIX /i18n
  BASE ${CMAKE_CURRENT_BINARY_DIR}
  FILES ${qm_files}
)

# Qt message localization
#
# On Nix, `QT6_INSTALL_TRANSLATIONS` contains an absolute path; elsewhere it is relative to
# the Qt install prefix. Qt does `${QT6_INSTALL_PREFIX}/${QT6_INSTALL_TRANSLATIONS}` in
# the implementation of `qt6_add_translations()`, which is why we can't use it with
# the `MERGE_QT_TRANSLATIONS` option.
#
include(QtInstallPaths OPTIONAL RESULT_VARIABLE qt_config_found)
if (NOT qt_config_found)
  include(${Qt6Core_DIR}/Qt6CoreConfigExtras.cmake) # required on Qt 6.4
endif()
cmake_path(ABSOLUTE_PATH QT6_INSTALL_TRANSLATIONS
  BASE_DIRECTORY ${QT6_INSTALL_PREFIX}
  OUTPUT_VARIABLE qt_translations_dir
)
message(VERBOSE "Using Qt6 translations: ${qt_translations_dir}")
file(GLOB qtbase_qm_files ${qt_translations_dir}/qtbase_*.qm)
qt6_add_resources(ChiPass_all "i18n_qtbase"
  PREFIX /i18n
  BASE ${qt_translations_dir}
  FILES ${qtbase_qm_files}
)


# Packaging for distribution
#
if (CHIPASS_DIST_TYPE_APP_BUNDLE)
  # For some cursed reason we could not figure out despite hours of trying, macdeployqt
  # refuses to install libqsvg.dylib and libqsvgicon.dylib. Note that this `install()` call
  # *must* happen before the following `install(SCRIPT ...)` call, otherwise install_name_tool
  # will not be called and the plugin will not load.
  install(
    DIRECTORY ${Qt6Svg_DIR}/../../qt-6/plugins/
    DESTINATION ${CHIPASS_BUNDLE_CONTENTS}/PlugIns
  )

  qt6_generate_deploy_app_script(
    TARGET ChiPass
    # For some reason, otool from the Nix build fails to strip many dylibs in the Nix build with
    # `unsupported load command (cmd=0x8000001f)` which refers to `LC_REEXPORT_DYLIB`. We disable
    # stripping here and let CPack do it.
    DEPLOY_TOOL_OPTIONS "-no-strip"
    OUTPUT_SCRIPT deploy_script
    NO_TRANSLATIONS
  )
  install(SCRIPT ${deploy_script})

  set(CPACK_SYSTEM_NAME "OSX")
  set(CPACK_STRIP_FILES ON)
  set(CPACK_GENERATOR "DragNDrop")
  set(CPACK_DMG_FORMAT "UDBZ")
  set(CPACK_DMG_VOLUME_NAME ${PROJECT_NAME})
  set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/share/macosx/background.tiff")
  set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_SOURCE_DIR}/share/macosx/DS_Store.scpt")
  set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${CHIPASS_VERSION}")
  include(CPack)
endif()


# Source code formatting
#
clang_format(format-source
  INCLUDE_GLOB *.cpp *.h *.mm
  EXCLUDE_REGEX
    "^streams/qtiocompressor\\."
    "^gui/KMessageWidget\\."
    "^gui/MainWindowAdaptor\\."
    "^gui/tag/TagsEdit\\."
)

