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

import QtQuick 2.4

import UM 1.4 as UM
import Cura 1.0 as Cura

Item
{
    // An Item whose bounds are guaranteed to be safe for overlays to be placed.
    // Defaults to parent, ie. the entire available area
    // eg. the layer slider will not be placed in this area.
    property var safeArea: parent


    property bool isSimulationPlaying: false
    readonly property real layerSliderSafeYMin: safeArea.y
    readonly property real layerSliderSafeYMax: safeArea.y + safeArea.height
    readonly property real pathSliderSafeXMin: safeArea.x + playButton.width
    readonly property real pathSliderSafeXMax: safeArea.x + safeArea.width

    visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity

    // A slider which lets users trace a single layer (XY movements)
    PathSlider
    {
        id: pathSlider

        readonly property real preferredWidth: UM.Theme.getSize("slider_layerview_size").height // not a typo, should be as long as layerview slider
        readonly property real margin: UM.Theme.getSize("default_margin").width
        readonly property real pathSliderSafeWidth: pathSliderSafeXMax - pathSliderSafeXMin

        height: UM.Theme.getSize("slider_handle").width
        width: preferredWidth + margin * 2 < pathSliderSafeWidth ? preferredWidth : pathSliderSafeWidth - margin * 2


        anchors.bottom: parent.bottom
        anchors.bottomMargin: margin

        anchors.horizontalCenter: parent.horizontalCenter
        anchors.horizontalCenterOffset: -(parent.width - pathSliderSafeXMax - pathSliderSafeXMin) / 2 // center between parent top and layerSliderSafeYMax


        visible: !UM.SimulationView.compatibilityMode

        // Custom properties
        handleValue: UM.SimulationView.currentPath
        maximumValue: UM.SimulationView.numPaths

        // Update values when layer data changes.
        Connections
        {
            target: UM.SimulationView
            function onMaxPathsChanged() { pathSlider.setHandleValue(UM.SimulationView.currentPath) }
            function onCurrentPathChanged()
            {
                // Only pause the simulation when the layer was changed manually, not when the simulation is running
                if (pathSlider.manuallyChanged)
                {
                    playButton.pauseSimulation()
                }
                pathSlider.setHandleValue(UM.SimulationView.currentPath)
            }
        }

        // Ensure that the slider handlers show the correct value after switching views.
        Component.onCompleted:
        {
            pathSlider.setHandleValue(UM.SimulationView.currentPath)
        }

    }

    UM.SimpleButton
    {
        id: playButton
        iconSource: Qt.resolvedUrl(!isSimulationPlaying ? "./resources/Play.svg": "./resources/Pause.svg")
        width: UM.Theme.getSize("small_button").width
        height: UM.Theme.getSize("small_button").height
        hoverColor: UM.Theme.getColor("slider_handle_active")
        color: UM.Theme.getColor("slider_handle")
        iconMargin: UM.Theme.getSize("thick_lining").width
        visible: !UM.SimulationView.compatibilityMode

        Connections
        {
            target: UM.Preferences
            function onPreferenceChanged(preference)
            {
                if (preference !== "view/only_show_top_layers" && preference !== "view/top_layer_count" && ! preference.match("layerview/"))
                {
                    return;
                }

                playButton.pauseSimulation()
            }
        }

        anchors
        {
            right: pathSlider.left
            verticalCenter: pathSlider.verticalCenter
        }

        onClicked:
        {
            if(isSimulationPlaying)
            {
                pauseSimulation()
            }
            else
            {
                resumeSimulation()
            }
        }

        function pauseSimulation()
        {
            UM.SimulationView.setSimulationRunning(false)
            simulationTimer.stop()
            isSimulationPlaying = false
            layerSlider.manuallyChanged = true
            pathSlider.manuallyChanged = true
        }

        function resumeSimulation()
        {
            UM.SimulationView.setSimulationRunning(true)
            simulationTimer.start()
            layerSlider.manuallyChanged = false
            pathSlider.manuallyChanged = false
        }
    }

    Timer
    {
        id: simulationTimer
        interval: 100
        running: false
        repeat: true
        onTriggered:
        {
            var currentPath = UM.SimulationView.currentPath
            var numPaths = UM.SimulationView.numPaths
            var currentLayer = UM.SimulationView.currentLayer
            var numLayers = UM.SimulationView.numLayers

            // When the user plays the simulation, if the path slider is at the end of this layer, we start
            // the simulation at the beginning of the current layer.
            if (!isSimulationPlaying)
            {
                if (currentPath >= numPaths)
                {
                    UM.SimulationView.setCurrentPath(0)
                }
                else
                {
                    UM.SimulationView.setCurrentPath(currentPath + 1)
                }
            }
            // If the simulation is already playing and we reach the end of a layer, then it automatically
            // starts at the beginning of the next layer.
            else
            {
                if (currentPath >= numPaths)
                {
                    // At the end of the model, the simulation stops
                    if (currentLayer >= numLayers)
                    {
                        playButton.pauseSimulation()
                    }
                    else
                    {
                        UM.SimulationView.setCurrentLayer(currentLayer + 1)
                        UM.SimulationView.setCurrentPath(0)
                    }
                }
                else
                {
                    UM.SimulationView.setCurrentPath(currentPath + 1)
                }
            }
            // The status must be set here instead of in the resumeSimulation function otherwise it won't work
            // correctly, because part of the logic is in this trigger function.
            isSimulationPlaying = true
        }
    }

    // Scrolls through Z layers
    LayerSlider
    {
        property var preferredHeight: UM.Theme.getSize("slider_layerview_size").height
        property double heightMargin: UM.Theme.getSize("default_margin").height * 3 // extra margin to accommodate layer number tooltips
        property double layerSliderSafeHeight: layerSliderSafeYMax - layerSliderSafeYMin

        id: layerSlider

        width: UM.Theme.getSize("slider_handle").width
        height: preferredHeight + heightMargin * 2 < layerSliderSafeHeight ? preferredHeight : layerSliderSafeHeight - heightMargin * 2

        anchors
        {
            right: parent.right
            verticalCenter: parent.verticalCenter
            verticalCenterOffset: -(parent.height - layerSliderSafeYMax - layerSliderSafeYMin) / 2 // center between parent top and layerSliderSafeYMax
            rightMargin: UM.Theme.getSize("default_margin").width
            bottomMargin: heightMargin
            topMargin: heightMargin
        }

        // Custom properties
        upperValue: UM.SimulationView.currentLayer
        lowerValue: UM.SimulationView.minimumLayer
        maximumValue: UM.SimulationView.numLayers

        // Update values when layer data changes
        Connections
        {
            target: UM.SimulationView
            function onMaxLayersChanged() { layerSlider.setUpperValue(UM.SimulationView.currentLayer) }
            function onMinimumLayerChanged() { layerSlider.setLowerValue(UM.SimulationView.minimumLayer) }
            function onCurrentLayerChanged()
            {
                // Only pause the simulation when the layer was changed manually, not when the simulation is running
                if (layerSlider.manuallyChanged)
                {
                    playButton.pauseSimulation()
                }
                layerSlider.setUpperValue(UM.SimulationView.currentLayer)
            }
        }

        // Make sure the slider handlers show the correct value after switching views
        Component.onCompleted:
        {
            layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
            layerSlider.setUpperValue(UM.SimulationView.currentLayer)
        }
    }
}