# Generate F3DIcon.h
add_executable(embed embed.cxx)
target_link_libraries(embed PUBLIC VTK::IOImage)

# On Windows, add VTK IOImage library to PATH
# It is required to run `embed` with `add_custom_command`
# Other systems supports RPATH so it is not required
if(WIN32)
  get_target_property(_confs VTK::IOImage IMPORTED_CONFIGURATIONS)
  foreach(_conf ${_confs})
    get_target_property(_runtime_path VTK::IOImage IMPORTED_LOCATION_${_conf})
    get_filename_component(_runtime_dir ${_runtime_path} DIRECTORY)
    list(APPEND CMAKE_MSVCIDE_RUN_PATH "${_runtime_dir}")
  endforeach()
endif()

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/F3DIcon.h
  COMMAND $<TARGET_FILE:embed>
    "${CMAKE_CURRENT_SOURCE_DIR}/../resources/logo32.png"
    "${CMAKE_CURRENT_BINARY_DIR}/F3DIcon.h"
  DEPENDS embed)

cmake_dependent_option(F3D_MACOS_BUNDLE "Build a macOS bundle application" ON "APPLE" OFF)
cmake_dependent_option(F3D_WINDOWS_GUI "Build a non-console Win32 application" ON "WIN32" OFF)

set(LIB_PLATFORM_SPECIFIC_FILES "")
set(EXEC_PLATFORM_SPECIFIC_FILES "")
if(WIN32)
  set(EXEC_PLATFORM_SPECIFIC_FILES "${CMAKE_SOURCE_DIR}/resources/f3d.rc")
  if(F3D_WINDOWS_GUI)
    set(LIB_PLATFORM_SPECIFIC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/vtkF3DWin32OutputWindow.cxx")
  endif()
endif()
if(APPLE)
  set(LIB_PLATFORM_SPECIFIC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/F3DNSDelegate.mm")
endif()

set(MODULES_SPECIFIC_SOURCE_FILES "")
set(MODULES_SPECIFIC_INCLUDE_DIRS "")
set(MODULES_SPECIFIC_LIBRARIES "")

configure_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/Config.h.in"
  "${CMAKE_CURRENT_BINARY_DIR}/Config.h"
  @ONLY)

configure_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/Config.cxx.in"
  "${CMAKE_CURRENT_BINARY_DIR}/Config.cxx"
  @ONLY)

# Readers declaration
macro(declare_f3d_reader reader)
  list(APPEND F3D_READER_FILES "readers/${reader}.h")
  set(F3D_READER_INCLUDES_CODE
    "${F3D_READER_INCLUDES_CODE}#include \"${reader}.h\"\n")
  set(F3D_READER_INSTANCES_CODE
    "${F3D_READER_INSTANCES_CODE}  ${reader} InstanceOf${reader};\n")
  set(F3D_READER_REGISTER_CODE
    "${F3D_READER_REGISTER_CODE}    F3DReaderFactory::Register(&InstanceOf${reader});\n")
  set(F3D_READER_UNREGISTER_CODE
    "${F3D_READER_UNREGISTER_CODE}    F3DReaderFactory::Unregister(&InstanceOf${reader});\n")
endmacro()

declare_f3d_reader(F3D3DSReader)
declare_f3d_reader(F3DCityGMLReader)
declare_f3d_reader(F3DDICOMReader)
declare_f3d_reader(F3DGLTFReader)
declare_f3d_reader(F3DMetaImageReader)
declare_f3d_reader(F3DNrrdReader)
declare_f3d_reader(F3DOBJReader)
declare_f3d_reader(F3DPLYReader)
declare_f3d_reader(F3DPTSReader)
declare_f3d_reader(F3DSTLReader)
declare_f3d_reader(F3DTIFFReader)
declare_f3d_reader(F3DVRMLReader)
declare_f3d_reader(F3DVTKLegacyReader)
declare_f3d_reader(F3DVTKXMLReader)

if(F3D_MODULE_OCCT)
  set(MODULES_SPECIFIC_SOURCE_FILES ${MODULES_SPECIFIC_SOURCE_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/vtkF3DOCCTReader.cxx")
  set(MODULES_SPECIFIC_INCLUDE_DIRS ${MODULES_SPECIFIC_INCLUDE_DIRS} ${OpenCASCADE_INCLUDE_DIR})
  # Note: OpenCASCADE does not declare the libs in the correct dependency order.
  # This could be an issue on Linux when linking with static libraries.
  # See .github/workflows/ci.yml for a scripted fix 
  set(MODULES_SPECIFIC_LIBRARIES ${MODULES_SPECIFIC_LIBRARIES} ${OpenCASCADE_LIBRARIES})
  
  declare_f3d_reader(F3DOpenCascadeReader)
endif()

if(F3D_MODULE_ASSIMP)
  set(MODULES_SPECIFIC_SOURCE_FILES ${MODULES_SPECIFIC_SOURCE_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/vtkF3DAssimpImporter.cxx")
  set(MODULES_SPECIFIC_LIBRARIES ${MODULES_SPECIFIC_LIBRARIES} assimp::assimp)

  # Note: Assimp CMake module file does not declare Debug target properties, just map it to Release properties
  get_target_property(F3D_ASSIMP_DEBUG_VAR assimp::assimp IMPORTED_IMPLIB_RELEASE)
  if(NOT F3D_ASSIMP_DEBUG_VAR)
    set_target_properties(assimp::assimp PROPERTIES MAP_IMPORTED_CONFIG_DEBUG Release)
  endif()

  declare_f3d_reader(F3DAssimpReader)
endif()

if(F3D_MODULE_EXODUS)
  declare_f3d_reader(F3DExodusIIReader)
endif()

# Generate the code of the F3DReaderInstantiator class
configure_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/F3DReaderInstantiator.h.in"
  "${CMAKE_CURRENT_BINARY_DIR}/F3DReaderInstantiator.h"
  @ONLY)

list(LENGTH F3D_READER_FILES F3D_NB_READERS)
message(STATUS "${F3D_NB_READERS} readers found.")

# configure_win32_exts and run it to create the NSIS install scripts
# for registering/unregistering available file extensions

if(WIN32)
  add_executable(configure_win32_exts
    configure_win32_exts.cxx
    readers/F3DReader.cxx
    readers/F3DReaderFactory.cxx
    "${CMAKE_CURRENT_BINARY_DIR}/F3DReaderInstantiator.h")

  target_compile_definitions(configure_win32_exts PUBLIC "-DF3D_NO_VTK")

  target_include_directories(configure_win32_exts PUBLIC
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/readers)

  add_custom_command(TARGET configure_win32_exts POST_BUILD
    COMMAND $<TARGET_FILE:configure_win32_exts>
      "${CMAKE_BINARY_DIR}/NSIS.RegisterCommands.nsh"
      "${CMAKE_BINARY_DIR}/NSIS.UnregisterCommands.nsh"
      "${CMAKE_BINARY_DIR}/F3DShellExtension.h"
    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/F3DReaderInstantiator.h")
endif()

# configure_linux_mime_types and run it to create the a dynamic mime_type
# list for registering/unregistering available mime types in .desktop
# and .thumbnailer file

if(UNIX AND NOT APPLE)
  add_executable(configure_linux_mime_types
    configure_linux_mime_types.cxx
    readers/F3DReader.cxx
    readers/F3DReaderFactory.cxx
    "${CMAKE_CURRENT_BINARY_DIR}/F3DReaderInstantiator.h")

  target_compile_definitions(configure_linux_mime_types PUBLIC "-DF3D_NO_VTK")

  target_include_directories(configure_linux_mime_types PUBLIC
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/readers)

  add_custom_command(TARGET configure_linux_mime_types POST_BUILD
    COMMAND $<TARGET_FILE:configure_linux_mime_types>
      "${CMAKE_BINARY_DIR}/mime_types"
    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/F3DReaderInstantiator.h")
endif()

# libf3d

set(F3D_SOURCE_FILES
  vtkF3DConsoleOutputWindow.cxx
  vtkF3DGenericImporter.cxx
  vtkF3DInteractorEventRecorder.cxx
  vtkF3DInteractorStyle.cxx
  vtkF3DMetaReader.cxx
  vtkF3DObjectFactory.cxx
  vtkF3DOpenGLGridMapper.cxx
  vtkF3DPolyDataMapper.cxx
  vtkF3DPostProcessFilter.cxx
  vtkF3DRenderPass.cxx
  vtkF3DRenderer.cxx
  vtkF3DRendererWithColoring.cxx
  F3DAnimationManager.cxx
  F3DLoader.cxx
  F3DLog.cxx
  F3DOffscreenRender.cxx
  F3DOptions.cxx
  readers/F3DReader.cxx
  readers/F3DReaderFactory.cxx
  ${CMAKE_CURRENT_BINARY_DIR}/Config.cxx
  ${MODULES_SPECIFIC_SOURCE_FILES}
  )

set(F3D_HEADER_FILES
  vtkF3DConsoleOutputWindow.h
  vtkF3DGenericImporter.h
  vtkF3DInteractorEventRecorder.h
  vtkF3DInteractorStyle.h
  vtkF3DMetaReader.h
  vtkF3DObjectFactory.h
  vtkF3DOpenGLGridMapper.h
  vtkF3DPolyDataMapper.h
  vtkF3DPostProcessFilter.h
  vtkF3DRenderPass.h
  vtkF3DRenderer.h
  vtkF3DRendererWithColoring.h
  F3DAnimationManager.h
  F3DLoader.h
  F3DLog.h
  F3DOffscreenRender.cxx
  F3DOptions.cxx
  readers/F3DReader.h
  readers/F3DReaderFactory.h
  ${CMAKE_CURRENT_BINARY_DIR}/F3DIcon.h
  ${CMAKE_CURRENT_BINARY_DIR}/F3DReaderInstantiator.h
  )

# Force static library when creating a macOS bundle
set(F3D_LIBRARY_TYPE "")
if(F3D_MACOS_BUNDLE)
  set(F3D_LIBRARY_TYPE "STATIC")
endif()

add_library(libf3d ${F3D_LIBRARY_TYPE}
  ${F3D_SOURCE_FILES}
  ${F3D_HEADER_FILES}
  ${F3D_READER_FILES}
  ${LIB_PLATFORM_SPECIFIC_FILES}
  )

target_include_directories(libf3d PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/readers
  ${CMAKE_CURRENT_BINARY_DIR}
  ${MODULES_SPECIFIC_INCLUDE_DIRS}
  )

set_target_properties(libf3d PROPERTIES
  ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
  WINDOWS_EXPORT_ALL_SYMBOLS ON
  PREFIX ""
  )

vtk_module_autoinit(TARGETS libf3d MODULES ${F3D_VTK_MODULES})

target_link_libraries(libf3d PUBLIC ${F3D_VTK_MODULES} ${MODULES_SPECIFIC_LIBRARIES})

set(F3D_STRICT_BUILD OFF CACHE BOOL "Use strict warnings and errors flags for building F3D")
mark_as_advanced(F3D_STRICT_BUILD)
if(F3D_STRICT_BUILD)
  if(MSVC)
    # Warning C4275 is essentially noise, disabling it to silent an issue with jsoncpp library
    target_compile_options(libf3d PUBLIC /W4 /WX /wd4275)
  else()
    target_compile_options(libf3d PUBLIC -Wall -Wextra -Werror)
  endif()
endif()

# Create man
if(F3D_GENERATE_MAN)
  find_program(HELP2MAN help2man)
  find_program(GZIP gzip)
  if (HELP2MAN AND GZIP)
    set(MAN_OUTPUT_FILE ${CMAKE_BINARY_DIR}/f3d.1)
    add_custom_command(
      OUTPUT ${MAN_OUTPUT_FILE}
      COMMAND ${HELP2MAN} $<TARGET_FILE:f3d> -N > ${MAN_OUTPUT_FILE}
      COMMAND ${GZIP} -f ${MAN_OUTPUT_FILE}
      DEPENDS f3d)
    add_custom_target(man ALL DEPENDS ${MAN_OUTPUT_FILE})
  else (HELP2MAN)
    message(WARNING "help2man or gzip not found, cannot create man entry")
  endif()
endif()

# coverage
cmake_dependent_option(F3D_COVERAGE "Emit coverage files" OFF "UNIX" OFF)
if(F3D_COVERAGE)
  target_compile_options(libf3d PUBLIC -g -O0 --coverage)
  target_link_options(libf3d PUBLIC --coverage)
endif()

# f3d

add_executable(f3d main.cxx ${EXEC_PLATFORM_SPECIFIC_FILES})
target_link_libraries(f3d PUBLIC libf3d)
set_target_properties(f3d PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
if (APPLE)
  set_target_properties(f3d PROPERTIES INSTALL_RPATH @loader_path/../lib)
elseif (UNIX)
  set_target_properties(f3d PROPERTIES INSTALL_RPATH $ORIGIN/../lib)
endif ()

if(F3D_STRICT_BUILD)
  if(MSVC)
    # Warning C4275 is essentially noise, disabling it to silent an issue with jsoncpp library
    target_compile_options(f3d PUBLIC /W4 /WX /wd4275)
  else()
    target_compile_options(f3d PUBLIC -Wall -Wextra -Werror)
  endif()
endif()

# MacOS Bundle app
if(F3D_MACOS_BUNDLE)
  set_target_properties(f3d PROPERTIES MACOSX_BUNDLE TRUE)

  # Add default configuration
  if(F3D_INSTALL_DEFAULT_CONFIGURATION_FILE)
    set(f3d_CONFIG ${CMAKE_SOURCE_DIR}/resources/config.json)
    set_source_files_properties(${f3d_CONFIG} PROPERTIES
      MACOSX_PACKAGE_LOCATION "Resources")
    target_sources(f3d PRIVATE ${f3d_CONFIG})
  endif()

  # Add logo icon
  set(MACOSX_BUNDLE_ICON_FILE logo.icns)
  set(f3d_ICON ${CMAKE_SOURCE_DIR}/resources/logo.icns)
  set_source_files_properties(${f3d_ICON} PROPERTIES
    MACOSX_PACKAGE_LOCATION "Resources")
  target_sources(f3d PRIVATE ${f3d_ICON})
  configure_file("${CMAKE_SOURCE_DIR}/resources/BundleInfo.plist.in"
    "${CMAKE_CURRENT_BINARY_DIR}/BundleInfo.plist")
  set_target_properties(f3d PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/BundleInfo.plist")
endif()

# Windows executable without console
if(WIN32)
  if(F3D_WINDOWS_GUI)
    set_target_properties(f3d PROPERTIES WIN32_EXECUTABLE TRUE)
  else()
    # force usage of wWinMainCRTStartup in console mode for Unicode support
    target_link_options(f3d PUBLIC "/ENTRY:wWinMainCRTStartup")
  endif()
endif()

if(BUILD_WINDOWS_SHELL_THUMBNAILS_EXTENSION)
  add_subdirectory(winshellext)
endif()
