include_guard(GLOBAL)

function(myx_target_setup_qt TARGET_NAME)
  set(options)
  set(oneValueArgs)
  set(multiValueArgs COMPONENTS PRIVATE PUBLIC_MOC PRIVATE_MOC UI QRC LANGS)

  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

  set(myx_qt_ver "5")
  if(QT_DEFAULT_MAJOR_VERSION)
    set(myx_qt_ver "${QT_DEFAULT_MAJOR_VERSION}")
  endif()

  if(NOT (myx_qt_ver STREQUAL "5" OR myx_qt_ver STREQUAL "6"))
    myx_message_fatal_error("Supported Qt versions are 5 and 6")
  endif()

  get_target_property(target_type ${TARGET_NAME} TYPE)

  foreach(iter ${ARG_COMPONENTS})
    if(target_type STREQUAL "INTERFACE_LIBRARY")
      target_include_directories(${TARGET_NAME} INTERFACE ${Qt${myx_qt_ver}${iter}_INCLUDE_DIRS})
    else()
      target_include_directories(${TARGET_NAME} PRIVATE ${Qt${myx_qt_ver}${iter}_INCLUDE_DIRS})
      if(NOT iter STREQUAL "LinguistTools")
        if(target_type STREQUAL "EXECUTABLE")
          target_link_libraries(${TARGET_NAME} PRIVATE Qt${myx_qt_ver}::${iter})
        endif()
        if(target_type STREQUAL "SHARED_LIBRARY")
          target_link_libraries(${TARGET_NAME} PUBLIC Qt${myx_qt_ver}::${iter})
        endif()
        if((${CMAKE_VERSION} VERSION_GREATER 3.8.0) AND (target_type STREQUAL "OBJECT_LIBRARY"))
          target_link_libraries(${TARGET_NAME} PUBLIC Qt${myx_qt_ver}::${iter})
        else()
          target_include_directories(${TARGET_NAME} PUBLIC ${Qt${myx_qt_ver}${iter}_INCLUDE_DIRS})
        endif()
      endif()
    endif()
  endforeach()

  foreach(iter ${ARG_PRIVATE})
    if(target_type STREQUAL "INTERFACE_LIBRARY")
      target_include_directories(${TARGET_NAME} INTERFACE ${Qt${myx_qt_ver}${iter}_PRIVATE_INCLUDE_DIRS})
    else()
      target_include_directories(${TARGET_NAME} PRIVATE ${Qt${myx_qt_ver}${iter}_PRIVATE_INCLUDE_DIRS})
    endif()
  endforeach()

  if(target_type STREQUAL "EXECUTABLE")
    target_compile_options(${TARGET_NAME} PRIVATE ${Qt${myx_qt_ver}Core_EXECUTABLE_COMPILE_FLAGS})
  endif()

  if(ARG_PUBLIC_MOC)
    set_property(TARGET ${TARGET_NAME} APPEND PROPERTY PUBLIC_HEADER_FILES "${ARG_PUBLIC_MOC}")
    set_property(TARGET ${TARGET_NAME} APPEND PROPERTY TR_FILES ${ARG_PUBLIC_MOC})
  endif()

  if(ARG_PRIVATE_MOC)
    set_property(TARGET ${TARGET_NAME} APPEND PROPERTY PRIVATE_HEADER_FILES "${ARG_PRIVATE_MOC}")
    set_property(TARGET ${TARGET_NAME} APPEND PROPERTY TR_FILES ${ARG_PRIVATE_MOC})
  endif()

  if(ARG_PUBLIC_MOC OR ARG_PRIVATE_MOC)
    if(myx_qt_ver EQUAL 5)
      qt5_wrap_cpp(moc_cpp ${ARG_PUBLIC_MOC} ${ARG_PRIVATE_MOC})
    elseif(myx_qt_ver EQUAL 6)
      qt6_wrap_cpp(moc_cpp ${ARG_PUBLIC_MOC} ${ARG_PRIVATE_MOC})
    endif()
  endif()

  if(ARG_QRC)
    if(myx_qt_ver EQUAL 5)
      qt5_add_resources(qrc_cpp ${ARG_QRC})
    elseif(myx_qt_ver EQUAL 6)
      qt6_add_resources(qrc_cpp ${ARG_QRC})
    endif()
  endif()

  if(ARG_UI)
    if(NOT COMMAND qt${myx_qt_ver}_wrap_ui)
      message(WARNING "MyxCMake: Widgets is required to process UI")
    else()
      if(myx_qt_ver EQUAL 5)
        qt5_wrap_ui(ui_h ${ARG_UI})
      elseif(myx_qt_ver EQUAL 6)
        qt6_wrap_ui(ui_h ${ARG_UI})
      endif()
      set_property(TARGET ${TARGET_NAME} APPEND PROPERTY TR_FILES ${ARG_UI})
      target_link_libraries(${TARGET_NAME} PRIVATE Qt${myx_qt_ver}::Widgets)
      # TODO
      target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_BINARY_DIR})
    endif()
  endif()

  # Перечень файлов, подлежащих переводу
  if(target_type STREQUAL "INTERFACE_LIBRARY")
    get_target_property(tr ${TARGET_NAME} INTERFACE_TR_FILES)
  else()
    get_target_property(tr ${TARGET_NAME} TR_FILES)
  endif()

  # Формирование файла ресурсов с переводами
  if(tr AND ARG_LANGS)
    if(NOT COMMAND qt${myx_qt_ver}_create_translation)
      message(WARNING "MyxCMake: LinguistTools is required to process LANGS")
    else()
      # Заглавие файла ресурсов
      file(WRITE ${PROJECT_BINARY_DIR}/${TARGET_NAME}_l10n.qrc "<RCC><qresource prefix=\"/l10n\">\n")
      # Для каждого языка, указанное в параметре LANGS
      foreach(iter ${ARG_LANGS})
        # Создание или обновление файла переводов в каталоге ${PROJECT_SOURCE_DIR}/l10n
        # и его компиляция в каталог ${PROJECT_BINARY_DIR}
        if(myx_qt_ver EQUAL 5)
          qt5_create_translation(qm ${tr}
            "${PROJECT_SOURCE_DIR}/l10n/${TARGET_NAME}_${iter}.ts"
            OPTIONS -I ${PROJECT_SOURCE_DIR}/include -I ${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME})
        elseif(myx_qt_ver EQUAL 6)
          qt6_create_translation(qm ${tr}
            "${PROJECT_SOURCE_DIR}/l10n/${TARGET_NAME}_${iter}.ts"
            OPTIONS -I ${PROJECT_SOURCE_DIR}/include -I ${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME})
        endif()
        # Добавление записи для скомпилированного файла переводов в ресурсный файл
        file(APPEND ${PROJECT_BINARY_DIR}/${TARGET_NAME}_l10n.qrc
          "<file alias=\"${TARGET_NAME}_${iter}.qm\">${TARGET_NAME}_${iter}.qm</file>\n")
        # Добавление скомпилированного файла переводов к списку зависимостей для цели
        target_sources(${TARGET_NAME} PRIVATE ${qm})
      endforeach()
      # Окончание файла ресурсов
      file(APPEND ${PROJECT_BINARY_DIR}/${TARGET_NAME}_l10n.qrc "</qresource></RCC>\n")
      # Компиляция файла ресурсов с переводами
      if(myx_qt_ver EQUAL 5)
        qt5_add_resources(qrc_l10n ${PROJECT_BINARY_DIR}/${TARGET_NAME}_l10n.qrc)
      elseif(myx_qt_ver EQUAL 6)
        qt6_add_resources(qrc_l10n ${PROJECT_BINARY_DIR}/${TARGET_NAME}_l10n.qrc)
      endif()
      target_sources(${TARGET_NAME} PRIVATE ${qrc_l10n})
    endif()
  endif()
  unset(tr)
  if(target_type STREQUAL "INTERFACE_LIBRARY")
    target_sources(${TARGET_NAME} INTERFACE ${ARG_PUBLIC_MOC} ${ARG_PRIVATE_MOC} ${moc_cpp} ${ui_h} ${qrc_cpp})
  else()
    target_sources(${TARGET_NAME} PRIVATE ${ARG_PUBLIC_MOC} ${ARG_PRIVATE_MOC} ${moc_cpp} ${ui_h} ${qrc_cpp})
  endif()

  # Установка публичных заголовочных файлов
  if(PROJECT_IS_TOP_LEVEL)
    myx_install_relative(${PROJECT_SOURCE_DIR}
      FILES ${ARG_PUBLIC_MOC}
      DESTINATION ${CMAKE_INSTALL_PREFIX}
      COMPONENT DEV
    )
  endif()
endfunction()