#-----------------------------------------------------------------------------
#
# Copyright (C) 2022 Bjarne von Horn <vh@igh.de>
#
# This file is part of the QtPdWidgets library.
#
# The QtPdWidgets library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# The QtPdWidgets library 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 Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with the QtPdWidgets Library. If not, see
# <http://www.gnu.org/licenses/>.
#
#-----------------------------------------------------------------------------

cmake_minimum_required(VERSION 3.10)

project(QtPdWidgets2 VERSION 2.0.0)

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

# Configure build

option(DESIGNER_PLUGIN "Build as Qt Designer plugin" ON)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(BUILD_EXAMPLE "Also build example" OFF)

# Load required packages

set(REQUIRED_PUBLIC_QT_MODULES Gui Widgets)
set(REQUIRED_QT_MODULES ${REQUIRED_PUBLIC_QT_MODULES} LinguistTools Svg Xml)
if(DESIGNER_PLUGIN)
    list(APPEND REQUIRED_QT_MODULES Designer)
endif()

find_package(QtPdCom1 REQUIRED)
find_package(Qt5 REQUIRED
    COMPONENTS ${REQUIRED_QT_MODULES}
)

# handle translation files

set(TS_FILES
    QtPdWidgets_de.ts
    QtPdWidgets_nl.ts
)

configure_file(QtPdWidgets_ts.qrc "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
qt5_add_translation(QM_FILES ${TS_FILES})

# add source files and headers

set(PUBLIC_HEADERS
    ${PROJECT_NAME}/Translator.h
    ${PROJECT_NAME}/ValueRing.h
    ${PROJECT_NAME}/Widget.h
    ${PROJECT_NAME}/Bar.h
    ${PROJECT_NAME}/CheckBox.h
    ${PROJECT_NAME}/ClipImage.h
    ${PROJECT_NAME}/CursorEditWidget.h
    ${PROJECT_NAME}/Dial.h
    ${PROJECT_NAME}/Digital.h
    ${PROJECT_NAME}/DoubleSpinBox.h
    ${PROJECT_NAME}/Export.h
    ${PROJECT_NAME}/Graph.h
    ${PROJECT_NAME}/Image.h
    ${PROJECT_NAME}/Led.h
    ${PROJECT_NAME}/MultiLed.h
    ${PROJECT_NAME}/NoPdTouchEdit.h
    ${PROJECT_NAME}/ParameterSetWidget.h
    ${PROJECT_NAME}/PushButton.h
    ${PROJECT_NAME}/RadioButton.h
    ${PROJECT_NAME}/Rotor.h
    ${PROJECT_NAME}/Scale.h
    ${PROJECT_NAME}/SendBroadcastWidget.h
    ${PROJECT_NAME}/Settings.h
    ${PROJECT_NAME}/SpinBox.h
    ${PROJECT_NAME}/Svg.h
    ${PROJECT_NAME}/TableView.h
    ${PROJECT_NAME}/Tank.h
    ${PROJECT_NAME}/Text.h
    ${PROJECT_NAME}/Time.h
    ${PROJECT_NAME}/TimeScale.h
    ${PROJECT_NAME}/TouchEdit.h
    ${PROJECT_NAME}/TouchEditDialog.h
    ${PROJECT_NAME}/XYGraph.h
)

set(SOURCES
    src/Bar.cpp
    src/BarSection.cpp
    src/BarSection.h
    src/BarStack.cpp
    src/BarStack.h
    src/CheckBox.cpp
    src/ClipImage.cpp
    src/CursorEditWidget.cpp
    src/Dial.cpp
    src/Digital.cpp
    src/DoubleSpinBox.cpp
    src/Graph.cpp
    src/Image.cpp
    src/Led.cpp
    src/MultiLed.cpp
    src/NoPdTouchEdit.cpp
    src/Parameter.cpp
    src/Parameter.h
    src/ParameterSetWidget.cpp
    src/PushButton.cpp
    src/RadioButton.cpp
    src/Rotor.cpp
    src/Scale.cpp
    src/SendBroadcastWidget.cpp
    src/Settings.cpp
    src/SpinBox.cpp
    src/Svg.cpp
    src/TableView.cpp
    src/Tank.cpp
    src/Text.cpp
    src/Time.cpp
    src/TimeScale.cpp
    src/TouchEdit.cpp
    src/TouchEditDialog.cpp
    src/Translator.cpp
    src/Version.cpp
    src/Widget.cpp
    src/XYGraph.cpp
)

if (DESIGNER_PLUGIN)
    list(APPEND SOURCES
        src/Plugin.h
        src/WidgetCollection.h
        src/Plugin.cpp
        src/WidgetCollection.cpp
    )
endif()

configure_file(QtPdWidgets2.h.in "${CMAKE_CURRENT_BINARY_DIR}/QtPdWidgets2.h")

add_library(${PROJECT_NAME}
    ${PUBLIC_HEADERS}
    ${SOURCES}

    ${QM_FILES}
    QtPdWidgets.qrc
    ${CMAKE_CURRENT_BINARY_DIR}/QtPdWidgets_ts.qrc
)

# bake in git revision

if (VERSION_HASH)
    # Hash was given as option, so write it directly
    # useful for OBS packaging
    file (WRITE "${CMAKE_CURRENT_BINARY_DIR}/git_revision_hash.h"
        "#define GIT_REV \"${VERSION_HASH}\"
")
else()
    # recompute hash on every `make` invocation
    # Note: CMake variable definitions (-D) must be before the -P option!
    add_custom_target (GitRevision
        BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/git_revision_hash.h"
        COMMAND ${CMAKE_COMMAND}
            -DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
            -DHASH_MACRO_NAME="GIT_REV"
            -DTARGET_FILE="${CMAKE_CURRENT_BINARY_DIR}/git_revision_hash.h"
            -P ${CMAKE_CURRENT_SOURCE_DIR}/git_revision.cmake
    )
    add_dependencies(${PROJECT_NAME} GitRevision)
endif()

# set include path

target_include_directories(${PROJECT_NAME} PUBLIC
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}>"
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
    "$<INSTALL_INTERFACE:include>"
)

# link to required and optional libraries

target_link_libraries(${PROJECT_NAME}
PUBLIC
    EtherLab::QtPdCom1
    Qt5::Core
    Qt5::Gui
    Qt5::Widgets
PRIVATE
    Qt5::Svg
    Qt5::Xml
)

if(DESIGNER_PLUGIN)
    # note: library is not installed into designer plugin directory on its own!
    target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Designer)
    target_compile_definitions(${PROJECT_NAME}
        PRIVATE "QDESIGNER_EXPORT_WIDGETS" "PD_QT5" "PD_IS_DESIGNER_PLUGIN"
    )
endif()

if(WIN32)
    # for gethostname in Process.cpp
    target_link_libraries(${PROJECT_NAME} PRIVATE -lwsock32)
endif()

# enable resource compiler etc.

set_target_properties(${PROJECT_NAME} PROPERTIES
    AUTOUIC ON
    AUTOMOC ON
    AUTORCC ON
    PUBLIC_HEADER "${PUBLIC_HEADERS}"
    CXX_VISIBILITY_PRESET "hidden"
    VISIBILITY_INLINES_HIDDEN 1
    VERSION ${PROJECT_VERSION}
    SOVERSION 2
)

target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)

# install library and headers

install(TARGETS ${PROJECT_NAME}
    EXPORT ${PROJECT_NAME}Targets
    ARCHIVE DESTINATION       "${CMAKE_INSTALL_LIBDIR}"
    LIBRARY DESTINATION       "${CMAKE_INSTALL_LIBDIR}"
    RUNTIME DESTINATION       "${CMAKE_INSTALL_BINDIR}"
    PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}"
)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/QtPdWidgets2.h"
    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

if (DESIGNER_PLUGIN)
    # Call qmake to query the plugin installation directory.
    get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake LOCATION)
    execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_PLUGINS
        OUTPUT_VARIABLE QT_INSTALL_PLUGINS OUTPUT_STRIP_TRAILING_WHITESPACE
    )

    # Install the library in QtDesigner plugin directory
    install(TARGETS ${PROJECT_NAME}
        LIBRARY DESTINATION ${QT_INSTALL_PLUGINS}/designer
        RUNTIME DESTINATION ${QT_INSTALL_PLUGINS}/designer
    )
endif()

# export target for use in other projects

set(ConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
configure_package_config_file(Config.cmake.in
        "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake"
    INSTALL_DESTINATION ${ConfigPackageLocation}
)
write_basic_package_version_file(
        "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}ConfigVersion.cmake"
    COMPATIBILITY SameMajorVersion
)

install(EXPORT ${PROJECT_NAME}Targets
    NAMESPACE EtherLab::
    FILE "${PROJECT_NAME}Targets.cmake"
    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
install(FILES
        "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake"
        "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}ConfigVersion.cmake"
    DESTINATION ${ConfigPackageLocation}
)
export(EXPORT ${PROJECT_NAME}Targets
    FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake"
    NAMESPACE EtherLab::
)

if(BUILD_EXAMPLE)
    add_library(EtherLab::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
    add_subdirectory(example)
endif()

configure_file(Doxyfile.in "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile" @ONLY)
