# Orthanc - A Lightweight, RESTful DICOM Store
# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
# Department, University Hospital of Liege, Belgium
# Copyright (C) 2017-2023 Osimis S.A., Belgium
# Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
# Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU Affero 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
# Affero General Public License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


cmake_minimum_required(VERSION 2.8...4.0)
project(OrthancWSIPlugin)

include(${CMAKE_SOURCE_DIR}/../Resources/CMake/Version.cmake)


#####################################################################
## Parameters of the build
#####################################################################

# Generic parameters
SET(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)")
SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
SET(STANDALONE_BUILD ON CACHE BOOL "Standalone build (all the resources are embedded, necessary for releases)")

# Advanced parameters to fine-tune linking against system libraries
SET(USE_SYSTEM_OPENJPEG ON CACHE BOOL "Use the system version of OpenJpeg")
SET(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK")
SET(ORTHANC_SDK_VERSION "1.12.9" CACHE STRING "Version of the Orthanc plugin SDK to use, if not using the system version (can be \"framework\", \"1.7.0\", or \"1.12.9\")")


#####################################################################
## Configure mandatory third-party components
#####################################################################

SET(ORTHANC_WSI_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
SET(USE_OPENJPEG_JP2 ON)

include(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/CMake/DownloadOrthancFramework.cmake)

if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system")
  if (ORTHANC_FRAMEWORK_USE_SHARED)
    # https://cmake.org/cmake/help/latest/policy/CMP0167.html
    if (CMAKE_VERSION VERSION_GREATER "3.30")
      find_package(Boost CONFIG)
    else()
      include(FindBoost)
    endif()

    find_package(Boost COMPONENTS thread)
    
    if (NOT Boost_FOUND)
      message(FATAL_ERROR "Unable to locate Boost on this system")
    endif()
    
    include(FindDCMTK)
    link_libraries(${Boost_LIBRARIES} ${DCMTK_LIBRARIES} jsoncpp)
  endif()

  add_definitions(-DORTHANC_ENABLE_DCMTK=1)
  link_libraries(${ORTHANC_FRAMEWORK_LIBRARIES})
  
else()
  include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkParameters.cmake)

  set(ENABLE_LOCALE OFF)         # Disable support for locales (notably in Boost)
  set(ENABLE_ZLIB ON)
  set(ENABLE_PNG ON)
  set(ENABLE_JPEG ON)

  include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/VisualStudioPrecompiledHeaders.cmake)
  include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkConfiguration.cmake)

  include_directories(${ORTHANC_FRAMEWORK_ROOT})
endif()

include(${ORTHANC_WSI_DIR}/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake)

# Include components specific to WSI
include(${ORTHANC_WSI_DIR}/Resources/CMake/Version.cmake)
include(${ORTHANC_WSI_DIR}/Resources/CMake/OpenJpegConfiguration.cmake)


#####################################################################
## Find the Orthanc SDK
#####################################################################

if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK)
  if (ORTHANC_SDK_VERSION STREQUAL "1.7.0")
    include_directories(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/Sdk-1.7.0)
  elseif (ORTHANC_SDK_VERSION STREQUAL "1.12.9")
    include_directories(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/Sdk-1.12.9)
  elseif (ORTHANC_SDK_VERSION STREQUAL "framework")
    include_directories(${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Include/)
  else()
    message(FATAL_ERROR "Unsupported version of the Orthanc plugin SDK: ${ORTHANC_SDK_VERSION}")
  endif()
else ()
  CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H)
  if (NOT HAVE_ORTHANC_H)
    message(FATAL_ERROR "Please install the headers of the Orthanc plugins SDK")
  endif()
endif()


#####################################################################
## Platform-specific configuration
#####################################################################

add_definitions(
  -DHAS_ORTHANC_EXCEPTION=1
  -DORTHANC_ENABLE_LOGGING_PLUGIN=1
  -DORTHANC_FRAMEWORK_BUILDING_PLUGIN=1
  )

if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
    ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
    ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
  link_libraries(rt)

elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
  execute_process(
    COMMAND 
    ${PYTHON_EXECUTABLE} ${ORTHANC_FRAMEWORK_ROOT}/../Resources/WindowsResources.py
    ${ORTHANC_WSI_VERSION} "OrthancWSI" OrthancWSI.dll "Whole-slide imaging plugin for Orthanc"
    ERROR_VARIABLE Failure
    OUTPUT_FILE ${AUTOGENERATED_DIR}/Version.rc
    )

  if (Failure)
    message(FATAL_ERROR "Error while computing the version information: ${Failure}")
  endif()

  list(APPEND AUTOGENERATED_SOURCES  ${AUTOGENERATED_DIR}/Version.rc)
endif()

if (APPLE)
  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation")
  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework CoreFoundation")
endif()


#####################################################################
## Prepare JavaScript libraries
#####################################################################

include(${CMAKE_SOURCE_DIR}/../Resources/CMake/JavaScriptLibraries.cmake)

if (STANDALONE_BUILD)
  add_definitions(-DORTHANC_STANDALONE=1)
  set(VIEWER_RESOURCES
    ANNOTATIONS_JS       ${CMAKE_SOURCE_DIR}/WebApplication/annotations.js
    VIEWER_HTML          ${CMAKE_SOURCE_DIR}/WebApplication/viewer.html
    VIEWER_JS            ${CMAKE_SOURCE_DIR}/WebApplication/viewer.js
    )
else()
  add_definitions(
    -DORTHANC_STANDALONE=0
    -DPLUGIN_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
    )
endif()

EmbedResources(
  ${VIEWER_RESOURCES}
  JAVASCRIPT_LIBS      ${JAVASCRIPT_LIBS_DIR}
  ORTHANC_EXPLORER     ${CMAKE_SOURCE_DIR}/OrthancExplorer.js
  MIRADOR_HTML         ${CMAKE_SOURCE_DIR}/WebApplication/mirador.html
  OPEN_SEADRAGON_HTML  ${CMAKE_SOURCE_DIR}/WebApplication/openseadragon.html
  )


#####################################################################
## Create the list of the source files that depend upon the
## precompiled headers
#####################################################################

set(ORTHANC_WSI_SOURCES
  DicomPyramidCache.cpp
  IAuthenticatedUser.cpp
  IIIF.cpp
  OrthancPluginConnection.cpp
  OrthancPyramidFrameFetcher.cpp
  Plugin.cpp
  RawTile.cpp
  UserId.cpp

  ${ORTHANC_WSI_DIR}/Framework/ColorSpaces.cpp
  ${ORTHANC_WSI_DIR}/Framework/DicomToolbox.cpp
  ${ORTHANC_WSI_DIR}/Framework/Enumerations.cpp
  ${ORTHANC_WSI_DIR}/Framework/ImageToolbox.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedPyramidCache.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedTiledPyramid.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramid.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidInstance.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidLevel.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramid.cpp
  ${ORTHANC_WSI_DIR}/Framework/Inputs/PyramidWithRawTiles.cpp
  ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Reader.cpp
  ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Writer.cpp

  ${ORTHANC_WSI_DIR}/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp
  ${ORTHANC_WSI_DIR}/Resources/Orthanc/Stone/DicomDatasetReader.cpp
  ${ORTHANC_WSI_DIR}/Resources/Orthanc/Stone/FullOrthancDataset.cpp
  ${ORTHANC_WSI_DIR}/Resources/Orthanc/Stone/IOrthancConnection.cpp
  ${ORTHANC_WSI_DIR}/Resources/Orthanc/StoneToolbox.cpp
  )


#####################################################################
## Setup precompiled headers for Microsoft Visual Studio
#####################################################################

if (MSVC)
  add_definitions(-DORTHANC_USE_PRECOMPILED_HEADERS=1)

  ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS(
    "PrecompiledHeaders.h" "${ORTHANC_FRAMEWORK_ROOT}/PrecompiledHeaders.cpp"
    ORTHANC_CORE_SOURCES_INTERNAL ORTHANC_CORE_PCH)

  ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS(
    "PrecompiledHeadersWSI.h" "${ORTHANC_WSI_DIR}/Framework/PrecompiledHeadersWSI.cpp"
    ORTHANC_WSI_SOURCES ORTHANC_WSI_PCH)

  source_group(ThirdParty\\OrthancCore FILES ${ORTHANC_CORE_SOURCES})
endif()


#####################################################################
## Create the plugin
#####################################################################

add_library(OrthancWSI SHARED
  ${ORTHANC_WSI_PCH}
  ${ORTHANC_WSI_SOURCES}
  ${ORTHANC_CORE_PCH}
  ${ORTHANC_CORE_SOURCES_INTERNAL}
  ${ORTHANC_CORE_SOURCES_DEPENDENCIES}
  ${AUTOGENERATED_SOURCES}
  ${OPENJPEG_SOURCES}
  )

if (COMMAND DefineSourceBasenameForTarget)
  DefineSourceBasenameForTarget(OrthancWSI)
endif()

message("Setting the version of the library to ${ORTHANC_WSI_VERSION}")
set_target_properties(OrthancWSI PROPERTIES 
  VERSION ${ORTHANC_WSI_VERSION} 
  SOVERSION ${ORTHANC_WSI_VERSION})

install(
  TARGETS OrthancWSI
  RUNTIME DESTINATION lib    # Destination for Windows
  LIBRARY DESTINATION share/orthanc/plugins    # Destination for Linux
  )
