cmake_minimum_required(VERSION 3.16)
project(CmvrControlStation VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/ui")
set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMVR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
set(CMVR_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(CMVR_TOOLS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tools")
set(CMVR_CERT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/certs")
set(PROTO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/protos")
set(GENERATED_ROOT "${CMAKE_CURRENT_BINARY_DIR}/generated_cpp")
set(PROTOC "${CMVR_TOOLS_DIR}/run_protoc.cmd")
set(GRPC_CPP_PLUGIN "${CMVR_TOOLS_DIR}/grpc_cpp_plugin.exe")

foreach(REQUIRED_FILE IN ITEMS
    "${PROTOC}"
    "${GRPC_CPP_PLUGIN}"
    "${CMVR_LIB_DIR}/libgrpc++.a"
    "${CMVR_LIB_DIR}/libprotobuf.a"
    "${CMVR_LIB_DIR}/libavcodec.dll.a"
    "${CMVR_LIB_DIR}/liburdfdom_model.dll.a"
    "${CMVR_LIB_DIR}/msquic.dll")
    if(NOT EXISTS "${REQUIRED_FILE}")
        message(FATAL_ERROR "Required local dependency not found: ${REQUIRED_FILE}")
    endif()
endforeach()

find_package(Qt5 5.12 REQUIRED COMPONENTS
    Core Gui Widgets Multimedia 3DCore 3DRender 3DExtras 3DInput)

add_executable(CmvrControlStation WIN32
    src/audiostreammanager.cpp
    src/audiostreammanager.h
    src/configeditorwidget.cpp
    src/configeditorwidget.h
    src/main.cpp
    src/mainwindow.cpp
    src/mainwindow_ui.cpp
    src/mainwindow.h
    src/quictestserver.cpp
    src/quictestserver.h
    src/rpcservicewidget.cpp
    src/rpcservicewidget.h
    src/robotclient.cpp
    src/robotclient.h
    src/trendwidget.cpp
    src/trendwidget.h
    src/urdfviewerwidget.cpp
    src/urdfviewerwidget.h
    src/videodecoder.cpp
    src/videodecoder.h
    ui/mainwindow.ui
    ui/systemservicepage.ui
    ui/armservicepage.ui
    ui/cameraservicepage.ui
    ui/agvservicepage.ui
    ui/audioservicepage.ui
    ui/quicserverpage.ui
    ui/diagnosticspage.ui
    ui/rpcservicewidget.ui
    resources.qrc)

set_target_properties(CmvrControlStation PROPERTIES
    DEBUG_POSTFIX "_d"
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/$<LOWER_CASE:$<CONFIG>>")

target_compile_definitions(CmvrControlStation PRIVATE
    _WIN32_WINNT=0x0600 CMVR_WITH_GRPC=1)
target_include_directories(CmvrControlStation PRIVATE
    "${CMVR_INCLUDE_DIR}"
    "${CMVR_INCLUDE_DIR}/urdfdom_headers"
    "${GENERATED_ROOT}")
target_link_libraries(CmvrControlStation PRIVATE
    Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Multimedia
    Qt5::3DCore Qt5::3DRender Qt5::3DExtras Qt5::3DInput)

set(PROTO_NAMES
    cmvr/api/common
    cmvr/msgs/agv
    cmvr/api/agv_command
    cmvr/api/agv_service
    cmvr/api/arm_command
    cmvr/api/arm_service
    cmvr/api/biohead_command
    cmvr/api/biohead_service
    cmvr/api/camera_command
    cmvr/api/camera_service
    cmvr/api/configuration_command
    cmvr/api/configuration_service
    cmvr/api/dexhand_command
    cmvr/api/dexhand_service
    cmvr/api/hlc_command
    cmvr/api/hlc_service
    cmvr/api/microphone_command
    cmvr/api/microphone_service
    cmvr/api/speaker_command
    cmvr/api/speaker_service
    cmvr/api/system_command
    cmvr/api/system_service
    cmvr/api/test_service
    cmvr/quic_edge/v1/quic_edge)
set(SERVICE_NAMES
    cmvr/api/agv_service
    cmvr/api/arm_service
    cmvr/api/biohead_service
    cmvr/api/camera_service
    cmvr/api/configuration_service
    cmvr/api/dexhand_service
    cmvr/api/hlc_service
    cmvr/api/microphone_service
    cmvr/api/speaker_service
    cmvr/api/system_service
    cmvr/api/test_service)

set(GENERATED_FILES)
foreach(PROTO_NAME IN LISTS PROTO_NAMES)
    set(PROTO_FILE "${PROTO_ROOT}/${PROTO_NAME}.proto")
    set(PB_CC "${GENERATED_ROOT}/${PROTO_NAME}.pb.cc")
    set(PB_H "${GENERATED_ROOT}/${PROTO_NAME}.pb.h")
    get_filename_component(PROTO_OUTPUT_DIR "${PB_CC}" DIRECTORY)
    add_custom_command(
        OUTPUT "${PB_CC}" "${PB_H}"
        COMMAND ${CMAKE_COMMAND} -E make_directory "${PROTO_OUTPUT_DIR}"
        COMMAND "${PROTOC}"
            --proto_path="${PROTO_ROOT}"
            --cpp_out="${GENERATED_ROOT}"
            "${PROTO_FILE}"
        DEPENDS "${PROTO_FILE}" "${PROTOC}"
        VERBATIM)
    list(APPEND GENERATED_FILES "${PB_CC}" "${PB_H}")
endforeach()

foreach(SERVICE_NAME IN LISTS SERVICE_NAMES)
    set(PROTO_FILE "${PROTO_ROOT}/${SERVICE_NAME}.proto")
    set(GRPC_CC "${GENERATED_ROOT}/${SERVICE_NAME}.grpc.pb.cc")
    set(GRPC_H "${GENERATED_ROOT}/${SERVICE_NAME}.grpc.pb.h")
    get_filename_component(PROTO_OUTPUT_DIR "${GRPC_CC}" DIRECTORY)
    add_custom_command(
        OUTPUT "${GRPC_CC}" "${GRPC_H}"
        COMMAND ${CMAKE_COMMAND} -E make_directory "${PROTO_OUTPUT_DIR}"
        COMMAND "${PROTOC}"
            --proto_path="${PROTO_ROOT}"
            --grpc_out="${GENERATED_ROOT}"
            --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}"
            "${PROTO_FILE}"
        DEPENDS "${PROTO_FILE}" "${PROTOC}" "${GRPC_CPP_PLUGIN}"
        VERBATIM)
    list(APPEND GENERATED_FILES "${GRPC_CC}" "${GRPC_H}")
endforeach()
target_sources(CmvrControlStation PRIVATE ${GENERATED_FILES})

file(GLOB ABSL_STATIC_LIBS "${CMVR_LIB_DIR}/libabsl_*.a")
target_link_libraries(CmvrControlStation PRIVATE
    "-Wl,--start-group"
    "${CMVR_LIB_DIR}/libgrpc++.a"
    "${CMVR_LIB_DIR}/libgrpc.a"
    "${CMVR_LIB_DIR}/libgpr.a"
    "${CMVR_LIB_DIR}/libaddress_sorting.a"
    "${CMVR_LIB_DIR}/libre2.a"
    "${CMVR_LIB_DIR}/libupb.a"
    "${CMVR_LIB_DIR}/libcares.a"
    "${CMVR_LIB_DIR}/libssl.a"
    "${CMVR_LIB_DIR}/libcrypto.a"
    "${CMVR_LIB_DIR}/libzlibstatic.a"
    "${CMVR_LIB_DIR}/libprotobuf.a"
    ${ABSL_STATIC_LIBS}
    "-Wl,--end-group"
    "${CMVR_LIB_DIR}/libavcodec.dll.a"
    "${CMVR_LIB_DIR}/libavutil.dll.a"
    "${CMVR_LIB_DIR}/libswscale.dll.a"
    "${CMVR_LIB_DIR}/liburdfdom_model.dll.a"
    ws2_32 crypt32 advapi32 bcrypt dbghelp iphlpapi secur32 ntdll)

file(GLOB CMVR_RUNTIME_DLLS "${CMVR_LIB_DIR}/*.dll")
foreach(RUNTIME_DLL IN LISTS CMVR_RUNTIME_DLLS)
    add_custom_command(TARGET CmvrControlStation POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${RUNTIME_DLL}" "$<TARGET_FILE_DIR:CmvrControlStation>")
endforeach()
foreach(CERTIFICATE IN ITEMS quic-test-server.pfx quic-test-ca.crt)
    add_custom_command(TARGET CmvrControlStation POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${CMVR_CERT_DIR}/${CERTIFICATE}"
            "$<TARGET_FILE_DIR:CmvrControlStation>/${CERTIFICATE}")
endforeach()
add_custom_command(TARGET CmvrControlStation POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E make_directory
        "$<TARGET_FILE_DIR:CmvrControlStation>/models"
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "${CMAKE_CURRENT_SOURCE_DIR}/models/demo_arm.urdf"
        "$<TARGET_FILE_DIR:CmvrControlStation>/models/demo_arm.urdf")

install(TARGETS CmvrControlStation RUNTIME DESTINATION bin)
