#-----------------------------------------------------------------------------
#
# Copyright (C) 2022 Bjarne von Horn <vh@igh.de>
#
# This file is part of the Qt6QmlPdWidgets library.
#
# The Qt6QmlPdWidgets 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 Qt6QmlPdWidgets 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 Qt6QmlPdWidgets Library. If not, see
# <http://www.gnu.org/licenses/>.
#
#-----------------------------------------------------------------------------

cmake_minimum_required(VERSION 3.19)

project(Qt6QmlPdWidgets1 VERSION 1.0.1)

set(LIBNAME Qt6QmlPdWidgets1)

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(BUILD_EXAMPLE "Build and install example" OFF)
option(GENERATE_QHP "Build Qt Assistant help files" OFF)

set(PUBLIC_QT_COMPONENTS Core Quick)

set(PRIVATE_QT_COMPONENTS Qml Xml Svg)
if (GENERATE_QHP)
    list(APPEND PRIVATE_QT_COMPONENTS Tools)
endif()

find_package(Qt6 6.3 REQUIRED
    COMPONENTS ${PUBLIC_QT_COMPONENTS} ${PRIVATE_QT_COMPONENTS} LinguistTools
)
find_package(Qt6PdCom1 1.4 REQUIRED COMPONENTS Qml)
qt_standard_project_setup()

if (NOT PD_QML_INSTALL_PATH)
    if (NOT QT6_INSTALL_QML)
        set(PD_QML_INSTALL_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/qt6/qml")
    else()
        set(PD_QML_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/${QT6_INSTALL_QML}")
    endif()
endif()

message(STATUS "Installing Qml Widgets to ${PD_QML_INSTALL_PATH}")

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

set(ALL_SOURCES
    src/QtPdCom_classes.h
    src/LiveSvg.cpp
    src/LiveSvg.h
    src/LiveSvg_p.h
    src/Qt6QmlPdWidgets.cpp
)

if (BUILD_SHARED_LIBS)
    qt6_add_library(${LIBNAME} SHARED ${ALL_SOURCES})
    qt6_add_library(${LIBNAME}_style SHARED)
else()
    qt6_add_library(${LIBNAME} STATIC ${ALL_SOURCES})
    qt6_add_library(${LIBNAME}_style STATIC)
endif()

set(QML_FILE_NAMES
    PdTouchEdit.qml
    Sprintf.js
    PdCheckBox.qml
    PdSlider.qml
    PdTimeLabel.qml
    PdSwitch.qml
    Pd.qml
    PdLed.qml
    PdText.qml
    PdToolButton.qml
    PdMultiLed.qml
    TouchEditDialog.qml
    PdComboBox.qml
    PdPushButton.qml
    PdBar.qml
    PdImage.qml
    PdLabel.qml
    PdDigital.qml
    LoginDialog.qml
    TouchEdit.qml
    PdTumbler.qml
)

set(QML_SOURCE_PREFIX "qml/de/igh/pd")

set(QML_FILES "")
foreach(QML_FILE ${QML_FILE_NAMES})
    set_source_files_properties("${QML_SOURCE_PREFIX}/${QML_FILE}" PROPERTIES
        QT_RESOURCE_ALIAS "${QML_FILE}"
    )
    list(APPEND QML_FILES "${QML_SOURCE_PREFIX}/${QML_FILE}")
endforeach()

set(ADDITIONAL_RESOURCE_NAMES
    FontAwesome.otf
)

set(PDQML_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/qml_out/de/igh/pd")

set(ADDITIONAL_RESOURCES "")
foreach(RESOURCE_FILE ${ADDITIONAL_RESOURCE_NAMES})
    set_source_files_properties("${QML_SOURCE_PREFIX}/${RESOURCE_FILE}" PROPERTIES
        QT_RESOURCE_ALIAS "${RESOURCE_FILE}"
        QT_QML_SOURCE_VERSIONS "${PROJECT_VERSION_MAJOR}.0"
    )
    list(APPEND ADDITIONAL_RESOURCES "${QML_SOURCE_PREFIX}/${RESOURCE_FILE}")
    configure_file("${QML_SOURCE_PREFIX}/${RESOURCE_FILE}" "${PDQML_OUTPUT_DIR}/${RESOURCE_FILE}" COPYONLY)
endforeach()

set_source_files_properties("${QML_SOURCE_PREFIX}/Pd.qml" PROPERTIES
    QT_QML_SINGLETON_TYPE TRUE
)

qt_add_qml_module(${LIBNAME}
    URI de.igh.pd
    VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
    IMPORTS de.igh.qtpdcom/1.4
    NO_PLUGIN_OPTIONAL
    QML_FILES
        ${QML_FILES}
    RESOURCES
        ${ADDITIONAL_RESOURCES}
    RESOURCE_PREFIX "/de.igh.pd${PROJECT_VERSION_MAJOR}/imports"
    OUTPUT_DIRECTORY "${PDQML_OUTPUT_DIR}"
    IMPORT_PATH "${CMAKE_CURRENT_BINARY_DIR}/qml_out;${QTPDCOM_QML_ROOT_PATH}"
    OUTPUT_TARGETS PD_QML_PLUGIN_TARGETS
)

set_source_files_properties("${QML_SOURCE_PREFIX}/style/Solarized.qml" PROPERTIES
    QT_RESOURCE_ALIAS "Solarized.qml"
    QT_QML_SINGLETON_TYPE TRUE
)

qt_add_qml_module(${LIBNAME}_style
    URI de.igh.pd.style
    VERSION 1.0
    QML_FILES
        "${QML_SOURCE_PREFIX}/style/Solarized.qml"
    RESOURCE_PREFIX "/de.igh.pd${PROJECT_VERSION_MAJOR}/imports"
    OUTPUT_DIRECTORY "${PDQML_OUTPUT_DIR}/style"
    IMPORT_PATH "${CMAKE_CURRENT_BINARY_DIR}/qml_out"
    OUTPUT_TARGETS PD_STYLE_QML_PLUGIN_TARGETS
)

if ("${Qt6_VERSION}" VERSION_GREATER_EQUAL "6.7")
    qt_add_translations(${LIBNAME}
        TS_FILES Qt6QmlPdWidgets_de.ts
        RESOURCE_PREFIX "/de.igh.pd${PROJECT_VERSION_MAJOR}/i18n"
        IMMEDIATE_CALL
        OUTPUT_TARGETS PD_TRANSLATION_TARGETS
    )
else()
    qt_add_translations(${LIBNAME}
        TS_FILES Qt6QmlPdWidgets_de.ts
        RESOURCE_PREFIX "/de.igh.pd${PROJECT_VERSION_MAJOR}/i18n"
        OUTPUT_TARGETS PD_TRANSLATION_TARGETS
    )
endif()

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


target_include_directories(${LIBNAME} PRIVATE
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/src"
)

target_link_libraries(${LIBNAME}
    PUBLIC
        Qt6::Core
        Qt6::Quick
    PRIVATE
        EtherLab::Qt6PdCom1
        Qt6::Qml
        Qt6::Svg
        Qt6::Xml
)

set(SOVERSION 1)

set_target_properties(${LIBNAME} PROPERTIES
    VISIBILITY_INLINES_HIDDEN 1
    CXX_VISIBILITY_PRESET "hidden"
    VERSION "${SOVERSION}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
    SOVERSION ${SOVERSION}
)
set_target_properties(${LIBNAME}_style PROPERTIES
    VISIBILITY_INLINES_HIDDEN 1
    CXX_VISIBILITY_PRESET "hidden"
    VERSION "${SOVERSION}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
    SOVERSION ${SOVERSION}
)

set(TARGETS_TO_INSTALL
    ${PD_STYLE_QML_PLUGIN_TARGETS}
    ${PD_QML_PLUGIN_TARGETS}
    ${PD_TRANSLATION_TARGETS}
    ${LIBNAME}
    ${LIBNAME}plugin
    ${LIBNAME}_style
    ${LIBNAME}_styleplugin
    ${LIBNAME}_qmldir
)

# add fake interface library to export QML install dir
# for both build and install directory
add_library(${LIBNAME}_qmldir INTERFACE)
set_target_properties(${LIBNAME}_qmldir PROPERTIES
    INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/qml_out>$<INSTALL_INTERFACE:${PD_QML_INSTALL_PATH}>"
)

# and install it
foreach(TARGET ${TARGETS_TO_INSTALL})
    install(TARGETS ${TARGET}
        EXPORT ${TARGET}Targets
        ARCHIVE DESTINATION       "${CMAKE_INSTALL_LIBDIR}"
        LIBRARY DESTINATION       "${CMAKE_INSTALL_LIBDIR}"
        RUNTIME DESTINATION       "${CMAKE_INSTALL_BINDIR}"
        OBJECTS DESTINATION       "${CMAKE_INSTALL_LIBDIR}/${LIBNAME}"
    )

    install(EXPORT ${TARGET}Targets
        NAMESPACE EtherLab::
        FILE ${TARGET}Targets.cmake
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${LIBNAME}
    )

    export(EXPORT ${TARGET}Targets
        FILE "${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}/${TARGET}Targets.cmake"
        NAMESPACE EtherLab::
    )
endforeach()

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

install(DIRECTORY "${PDQML_OUTPUT_DIR}"
    DESTINATION "${PD_QML_INSTALL_PATH}/de/igh"
    FILES_MATCHING
        PATTERN "qmldir"
        PATTERN "*.otf"
        PATTERN "*.qml"
        PATTERN "*.js"
        PATTERN "*.qmltypes"
)

install(TARGETS ${LIBNAME}_styleplugin
    ARCHIVE DESTINATION       "${CMAKE_INSTALL_LIBDIR}"
    LIBRARY DESTINATION       "${PD_QML_INSTALL_PATH}/de/igh/pd/style"
    RUNTIME DESTINATION       "${PD_QML_INSTALL_PATH}/de/igh/pd/style"
)

install(TARGETS ${LIBNAME}plugin
    ARCHIVE DESTINATION       "${CMAKE_INSTALL_LIBDIR}"
    LIBRARY DESTINATION       "${PD_QML_INSTALL_PATH}/de/igh/pd"
    RUNTIME DESTINATION       "${PD_QML_INSTALL_PATH}/de/igh/pd"
)


# and export it

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

## bake in git commit hash


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(${LIBNAME} GitRevision)
endif()


## Build example (optionally)

if (BUILD_EXAMPLE)
    add_library(EtherLab::${LIBNAME} ALIAS ${LIBNAME})
    add_library(EtherLab::${LIBNAME}_qmldir ALIAS ${LIBNAME}_qmldir)
    add_library(EtherLab::${LIBNAME}plugin ALIAS ${LIBNAME}plugin)
    add_library(EtherLab::${LIBNAME}_style ALIAS ${LIBNAME}_style)
    add_library(EtherLab::${LIBNAME}_styleplugin ALIAS ${LIBNAME}_styleplugin)
    set(PD_QML_ROOT_PATH "${CMAKE_CURRENT_BINARY_DIR}/qml_out")
    add_subdirectory(qml_test)
endif()

if (GENERATE_QHP)
    set(DOXYGEN_GENERATE_QHP "YES")
    get_target_property(DOXYGEN_QHG_LOCATION Qt6::qhelpgenerator IMPORTED_LOCATION)
else()
    set(DOXYGEN_GENERATE_QHP "NO")
endif()

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