/*
 *  SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
 *
 *  SPDX-License-Identifier: LGPL-2.0-or-later
 */

import QtQuick
import QtQuick.Templates as T

import org.kde.kirigami as Kirigami
import "templates/private" as TP
import "templates" as KT

/**
 * @brief An item that provides the features of AbstractApplicationWindow without the window itself.
 *
 * This allows embedding into a larger application.
 * Unless you need extra flexibility it is recommended to use ApplicationItem instead.
 *
 * Example usage:
 * @code
 * import org.kde.kirigami as Kirigami
 *
 * Kirigami.AbstractApplicationItem {
 *  [...]
 *     globalDrawer: Kirigami.GlobalDrawer {
 *         actions: [
 *            Kirigami.Action {
 *                text: "View"
 *                icon.name: "view-list-icons"
 *                Kirigami.Action {
 *                        text: "action 1"
 *                }
 *                Kirigami.Action {
 *                        text: "action 2"
 *                }
 *                Kirigami.Action {
 *                        text: "action 3"
 *                }
 *            },
 *            Kirigami.Action {
 *                text: "Sync"
 *                icon.name: "folder-sync"
 *            }
 *         ]
 *     }
 *
 *     contextDrawer: Kirigami.ContextDrawer {
 *         id: contextDrawer
 *     }
 *
 *     pageStack: Kirigami.PageRow {
 *         ...
 *     }
 *  [...]
 * }
 * @endcode
 *
 * @inherit QtQuick.Item
 */
Item {
    id: root

//BEGIN properties
    /**
     * @brief This property holds the stack used to allocate the pages and to manage the
     * transitions between them.
     *
     * Put a container here, such as QtQuick.Controls.StackView.
     */
    property Item pageStack

    /**
     * @brief This property holds the font for this item.
     *
     * default: ``Kirigami.Theme.defaultFont``
     */
    property font font: Kirigami.Theme.defaultFont

    /**
     * @brief This property holds the locale for this item.
     */
    property Locale locale

    /**
     * @brief This property holds an item that can be used as a menuBar for the application.
     */
    property T.MenuBar menuBar

    /**
    * @brief This property holds an item that can be used as a title for the application.
    *
    * Scrolling the main page will make it taller or shorter (through the point of going away).
    *
    * It's a behavior similar to the typical mobile web browser addressbar.
    *
    * The minimum, preferred and maximum heights of the item can be controlled with
    *
    * * ``Layout.minimumHeight``: default is 0, i.e. hidden
    * * ``Layout.preferredHeight``: default is Kirigami.Units.gridUnit * 1.6
    * * ``Layout.maximumHeight``: default is Kirigami.Units.gridUnit * 3
    *
    * To achieve a titlebar that stays completely fixed, just set the 3 sizes as the same.
    *
    * @property kirigami::templates::AbstractApplicationHeader header
    */
    property KT.AbstractApplicationHeader header

    /**
     * @brief This property holds an item that can be used as a footer for the application.
     */
    property Item footer

    /**
     * @brief This property sets whether the standard chrome of the app is visible.
     *
     * These are the action button, the drawer handles and the application header.
     *
     * default: ``true``
     */
    property bool controlsVisible: true

    /**
     * @brief This property holds the drawer for global actions.
     *
     * Thos drawer can be opened by sliding from the left screen edge
     * or by dragging the ActionButton to the right.
     *
     * @note It is recommended to use the GlobalDrawer here.
     * @property org::kde::kirigami::OverlayDrawer globalDrawer
     */
    property OverlayDrawer globalDrawer

    /**
     * @brief This property tells us whether the application is in "widescreen" mode.
     *
     * This is enabled on desktops or horizontal tablets.
     *
     * @note Different styles can have their own logic for deciding this.
     */
    property bool wideScreen: width >= Kirigami.Units.gridUnit * 60

    /**
     * @brief This property holds the drawer for context-dependent actions.
     *
     * The drawer that will be opened by sliding from the right screen edge
     * or by dragging the ActionButton to the left.
     *
     * @note It is recommended to use the ContextDrawer type here.
     *
     * The contents of the context drawer should depend from what page is
     * loaded in the main pageStack
     *
     * Example usage:
     *
     * @code
     * import org.kde.kirigami as Kirigami
     *
     * Kirigami.ApplicationWindow {
     *     contextDrawer: Kirigami.ContextDrawer {
     *         enabled: true
     *         actions: [
     *             Kirigami.Action {
     *                 icon.name: "edit"
     *                 text: "Action text"
     *                 onTriggered: {
     *                     // do stuff
     *                 }
     *             },
     *             Kirigami.Action {
     *                 icon.name: "edit"
     *                 text: "Action text"
     *                 onTriggered: {
     *                     // do stuff
     *                 }
     *             }
     *         ]
     *     }
     * }
     * @endcode
     *
     * @property org::kde::kirigami::ContextDrawer contextDrawer
     */
    property OverlayDrawer contextDrawer

    /**
     * @brief This property holds the list of all children of this item.
     * @internal
     * @property list<Object> __data
     */
    default property alias __data: contentItemRoot.data

    /**
     * @brief This property holds the Item of the main part of the Application UI.
     */
    readonly property Item contentItem: Item {
        id: contentItemRoot
        parent: root
        anchors {
            fill: parent
            topMargin: controlsVisible ? (root.header ? root.header.height : 0) + (root.menuBar ? root.menuBar.height : 0) : 0
            bottomMargin: controlsVisible && root.footer ? root.footer.height : 0
            leftMargin: root.globalDrawer && root.globalDrawer.modal === false ? root.globalDrawer.contentItem.width * root.globalDrawer.position : 0
            rightMargin: root.contextDrawer && root.contextDrawer.modal === false ? root.contextDrawer.contentItem.width * root.contextDrawer.position : 0
        }
    }

    /**
     * @brief This property holds the color for the background.
     *
     * default: ``Kirigami.Theme.backgroundColor``
     */
    property color color: Kirigami.Theme.backgroundColor

    /**
     * @brief This property holds the background of the Application UI.
     */
    property Item background

    property alias overlay: overlayRoot
//END properties

//BEGIN functions
    /**
     * @brief This function shows a little passive notification at the bottom of the app window
     * lasting for few seconds, with an optional action button.
     *
     * @param message The text message to be shown to the user.
     * @param timeout How long to show the message:
     *            possible values: "short", "long" or the number of milliseconds
     * @param actionText Text in the action button, if any.
     * @param callBack A JavaScript function that will be executed when the
     *            user clicks the button.
     */
    function showPassiveNotification(message, timeout, actionText, callBack) {
        notificationsObject.showNotification(message, timeout, actionText, callBack);
    }

    /**
     * @brief This function hides the passive notification at specified index, if any is shown.
     * @param index Index of the notification to hide. Default is 0 (oldest notification).
    */
    function hidePassiveNotification(index = 0) {
        notificationsObject.hideNotification(index);
    }

    /**
     * @brief This property gets application windows object anywhere in the application.
     * @returns a pointer to this item.
     */
    function applicationWindow() {
        return root;
    }
//END functions

//BEGIN signals handlers
    onMenuBarChanged: {
        if (menuBar) {
            menuBar.parent = root.contentItem
            if (menuBar instanceof T.ToolBar) {
                menuBar.position = T.ToolBar.Footer
            } else if (menuBar instanceof T.DialogButtonBox) {
                menuBar.position = T.DialogButtonBox.Footer
            }
            menuBar.width = Qt.binding(() => root.contentItem.width)
            // FIXME: (root.header.height ?? 0) when we can depend from 5.15
            menuBar.y = Qt.binding(() => -menuBar.height - (root.header.height ? root.header.height : 0))
        }
    }

    onHeaderChanged: {
        if (header) {
            header.parent = root.contentItem
            if (header instanceof T.ToolBar) {
                header.position = T.ToolBar.Header
            } else if (header instanceof T.DialogButtonBox) {
                header.position = T.DialogButtonBox.Header
            }
            header.width = Qt.binding(() => root.contentItem.width)
            header.y = Qt.binding(() => -header.height)
        }
    }

    onFooterChanged: {
        if (footer) {
            footer.parent = root.contentItem
            if (footer instanceof T.ToolBar) {
                footer.position = T.ToolBar.Footer
            } else if (footer instanceof T.DialogButtonBox) {
                footer.position = T.DialogButtonBox.Footer
            }
            footer.width = Qt.binding(() => root.contentItem.width)
            footer.y = Qt.binding(() => root.contentItem.height)
        }
    }

    onBackgroundChanged: {
        if (background) {
            background.parent = root.contentItem
            background.anchors.fill = background.parent
        }
    }

    onPageStackChanged: pageStack.parent = root.contentItem;
//END signals handlers

    LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
    LayoutMirroring.childrenInherit: true

    TP.PassiveNotificationsManager {
        id: notificationsObject
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        z: 1
    }

    Item {
        anchors.fill: parent
        parent: root.parent || root
        z: 999999

        Item {
            id: overlayRoot
            z: -1
            anchors.fill: parent
        }
    }

    // Don't use root.overlay property here. For one, we know that in a window
    // it will always be the same as T.Overlay.overlay; secondly Drawers
    // don't care about being contained/parented to anything else anyway.
    onGlobalDrawerChanged: {
        if (globalDrawer) {
            globalDrawer.parent = Qt.binding(() => visible ? T.Overlay.overlay : null);
        }
    }
    onContextDrawerChanged: {
        if (contextDrawer) {
            contextDrawer.parent = Qt.binding(() => visible ? T.Overlay.overlay : null);
        }
    }

    Window.onWindowChanged: {
        if (globalDrawer) {
            globalDrawer.visible = globalDrawer.drawerOpen;
        }
        if (contextDrawer) {
            contextDrawer.visible = contextDrawer.drawerOpen;
        }
    }

    implicitWidth: Kirigami.Settings.isMobile ? Kirigami.Units.gridUnit * 30 : Kirigami.Units.gridUnit * 55
    implicitHeight: Kirigami.Settings.isMobile ? Kirigami.Units.gridUnit * 45 : Kirigami.Units.gridUnit * 40
    visible: true
}
