// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.

import QtQuick 2.2
import QtQuick.Controls 2.0
import UM 1.3 as UM

/**
 * This is a generic pop-up element which can be supplied with a target and a content item. The
 * content item will appear to the left, right, above, or below the target depending on the value of
 * the direction property
 */
Popup
{
    id: base

    /**
     * The target item is what the pop-up is "tied" to, usually a button
     */
    property var target

    /**
     * Which direction should the pop-up "point"?
     * Possible values include:
     *   - "up"
     *   - "down"
     *   - "left"
     *   - "right"
     */
    property string direction: "down"

    /**
     * We save the default direction so that if a pop-up was flipped but later has space (i.e. it
     * moved), we can unflip it back to the default direction.
     */
    property string originalDirection: ""

    /**
     * Should the popup close when you click outside it? For example, this is
     * disabled by the InfoBlurb component since it's opened and closed using mouse
     * hovers, not clicks.
     */
    property bool closeOnClick: true

    /**
     * Use white for context menus, dark grey for info blurbs!
     */
    property var color: "#ffffff" // TODO: Theme!

    Component.onCompleted:
    {
        recalculatePosition()

        // Set the direction here so it's only set once and never mutated
        originalDirection = (' ' + direction).slice(1)
    }

    background: Item
    {
        anchors.fill: parent

        Item
        {
            id: pointedRectangle
            anchors
            {
                horizontalCenter: parent.horizontalCenter
                verticalCenter: parent.verticalCenter
            }
            height: parent.height - 10 * screenScaleFactor // Because of the shadow
            width: parent.width - 10 * screenScaleFactor // Because of the shadow

            Rectangle
            {
                id: point
                anchors
                {
                    horizontalCenter:
                    {
                        switch(direction)
                        {
                            case "left":
                                return bloop.left
                            case "right":
                                return bloop.right
                            default:
                                return bloop.horizontalCenter
                        }
                    }
                    verticalCenter:
                    {
                        switch(direction)
                        {
                            case "up":
                                return bloop.top
                            case "down":
                                return bloop.bottom
                            default:
                                return bloop.verticalCenter
                        }
                    }
                }
                color: base.color
                height: 12 * screenScaleFactor
                transform: Rotation
                {
                    angle: 45
                    origin.x: point.width / 2
                    origin.y: point.height / 2
                }
                width: height
            }

            Rectangle
            {
                id: bloop
                anchors
                {
                    fill: parent
                    leftMargin:   direction == "left"  ? 8 * screenScaleFactor : 0
                    rightMargin:  direction == "right" ? 8 * screenScaleFactor : 0
                    topMargin:    direction == "up"    ? 8 * screenScaleFactor : 0
                    bottomMargin: direction == "down"  ? 8 * screenScaleFactor : 0
                }
                color: base.color
                width: parent.width
            }
        }
    }

    visible: false
    onClosed: visible = false
    onOpened:
    {
        // Flip orientation if necessary
        recalculateOrientation()

        // Fix position if necessary
        recalculatePosition()

        // Show the pop up
        visible = true
    }
    closePolicy: closeOnClick ? Popup.CloseOnPressOutside : Popup.NoAutoClose

    clip: true

    padding: UM.Theme.getSize("monitor_shadow_radius").width
    topPadding:    direction == "up"    ? padding + 8 * screenScaleFactor : padding
    bottomPadding: direction == "down"  ? padding + 8 * screenScaleFactor : padding
    leftPadding:   direction == "left"  ? padding + 8 * screenScaleFactor : padding
    rightPadding:  direction == "right" ? padding + 8 * screenScaleFactor : padding

    function recalculatePosition() {

        // Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
        const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
        const realHeight = contentItem.implicitHeight + topPadding + bottomPadding

        var centered = {
            x: target.x + target.width / 2 - realWidth / 2,
            y: target.y + target.height / 2 - realHeight / 2
        }

        switch(direction)
        {
            case "left":
                x = target.x + target.width
                y = centered.y
                break
            case "right":
                x = target.x - realWidth
                y = centered.y
                break
            case "up":
                x = centered.x
                y = target.y + target.height
                break
            case "down":
                x = centered.x
                y = target.y - realHeight
                break
        }
    }

    function recalculateOrientation() {
        var availableSpace
        var targetPosition = target.mapToItem(monitorFrame, 0, 0)

        // Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
        const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
        const realHeight = contentItem.implicitHeight + topPadding + bottomPadding

        switch(originalDirection)
        {
            case "up":
                availableSpace = monitorFrame.height - (targetPosition.y + target.height)
                direction = availableSpace < realHeight ? "down" : originalDirection
                break
            case "down":
                availableSpace = targetPosition.y
                direction = availableSpace < realHeight ? "up" : originalDirection
                break
            case "right":
                availableSpace = targetPosition.x
                direction = availableSpace < realWidth ? "left" : originalDirection
                break
            case "left":
                availableSpace = monitorFrame.width - (targetPosition.x + target.width)
                direction = availableSpace < realWidth ? "right" : originalDirection
                break
        }
    }
}
