include_guard(GLOBAL)

function(myx_target_setup NAME)
  set(options)
  set(oneValueArgs PCH)
  set(multiValueArgs COMPILE_DEFINITIONS PACKAGES LINK_LIBRARIES
                     CPP INTERFACE_HEADERS PUBLIC_HEADERS PRIVATE_HEADERS)

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

  if(NOT TARGET ${NAME})
    myx_message_fatal_error("Target ${NAME} does not exists.")
  endif()

  get_target_property(target_type ${NAME} TYPE)

  foreach(iter ${ARG_PACKAGES})
    target_include_directories(${NAME} PRIVATE ${${iter}_INCLUDE_DIRS})
    target_compile_definitions(${NAME} PRIVATE ${${iter}_COMPILE_DEFINITIONS})
  endforeach()
  target_compile_definitions(${NAME} PRIVATE ${ARG_COMPILE_DEFINITIONS})

  if(ARG_CPP)
    set_property(TARGET ${NAME} APPEND PROPERTY CPP_FILES ${ARG_CPP})
    set_property(TARGET ${NAME} APPEND PROPERTY TR_FILES ${ARG_CPP})
  endif()

  if(ARG_PUBLIC_HEADERS)
    set_property(TARGET ${NAME} APPEND PROPERTY PUBLIC_HEADER_FILES "${ARG_PUBLIC_HEADERS}")
    set_property(TARGET ${NAME} APPEND PROPERTY TR_FILES ${ARG_PUBLIC_HEADERS})
  endif()

  if(ARG_PRIVATE_HEADERS)
    set_property(TARGET ${NAME} APPEND PROPERTY PRIVATE_HEADER_FILES "${ARG_PRIVATE_HEADERS}")
    set_property(TARGET ${NAME} APPEND PROPERTY TR_FILES ${ARG_PRIVATE_HEADERS})
  endif()

  if(ARG_PCH)
    if((${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.16) AND (PROJECT_IS_TOP_LEVEL OR MYX_USE_LOCAL_DIRECTORIES))
      target_precompile_headers(${NAME} PRIVATE ${ARG_PCH})
    else()
      target_compile_options(${NAME} PRIVATE -include ${ARG_PCH})
    endif()
    set_property(TARGET ${NAME} APPEND PROPERTY PRIVATE_HEADER_FILES "${ARG_PCH}")
  endif()

  if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
    target_include_directories(${PROJECT_NAME} PRIVATE
      $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>)

    if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/src")
      target_include_directories(${PROJECT_NAME} PRIVATE
        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
    endif()
  endif()

  if(target_type STREQUAL "EXECUTABLE")
    if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/include")
      target_include_directories(${PROJECT_NAME} PRIVATE
        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
    endif()

    set_target_properties(${NAME} PROPERTIES
      POSITION_INDEPENDENT_CODE ON
      RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
    )
    if(CMAKE_CXX_COMPILE_OPTIONS_PIE)
      target_compile_options(${NAME} PUBLIC ${CMAKE_CXX_COMPILE_OPTIONS_PIE})
    endif()
    install(TARGETS ${NAME} COMPONENT main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
  endif()

  target_sources(${NAME} PUBLIC $<BUILD_INTERFACE:${ARG_INTERFACE_HEADERS}>)
  target_sources(${NAME} PUBLIC ${ARG_PUBLIC_HEADERS})
  target_sources(${NAME} PRIVATE ${ARG_CPP} ${ARG_PCH} ${ARG_PRIVATE_HEADERS})
  if(NOT target_type STREQUAL "OBJECT_LIBRARY")
    target_link_libraries(${NAME} PRIVATE ${ARG_LINK_LIBRARIES})
  endif()
  target_compile_definitions(${NAME} PRIVATE ${ARG_COMPILE_DEFINITIONS})

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