/*!
 *
 * Copyright (c) 2020-2023 Diality Inc. - All Rights Reserved.
 * \copyright
 * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN
 * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER.
 *
 * \file    Slider.qml
 * \author  (last)      Behrouz NematiPour
 * \date    (last)      10-Feb-2023
 * \author  (original)  Behrouz NematiPour
 * \date    (original)  18-Mar-2020
 *
 */

// Qt
import QtQuick 2.12

// Project
//  Qml imports
import "qrc:/globals"

/*!
 * \brief   Denali project ProgressBar
 */
RangeRect { id: _root
    property alias  value              : _progressRect.value

    property real   step               : 1
    property bool   stepSnap           : false

    property bool   ticks              : false

    property alias  color              : _progressRect.color
    property alias  bgColor            : _root.color

    property alias  handler            : _handler
    property alias  handlerColor       : _handler.color
    property alias  handlerVisible     : _handler.visible

    property alias  diameter           : _handler.diameter

    property bool   isActive           : true
    property bool   inActiveZero       : false  // if inActiveZero:true, when is not active (inActive or active:false) sets to zero instead of minimum

    property alias  progressRectMargin : _progressRect.margin

    property int    tickMarksThickness : 2

    signal progressRectClicked()
    signal progressRectDragged()
    signal activeChanged()

    function setActive(active) {
        if (active) {
            color = Colors.createTreatmentActive
            handlerColor = Colors.createTreatmentActive
        } else {
            color = Colors.createTreatmentInactive
            handlerColor = Colors.createTreatmentInactive
        }

        if (active !== isActive) {
            isActive = active;
            activeChanged()
        }
    }

    onIsActiveChanged: {
        setActive(isActive)
        if (!isActive) {
            value = inActiveZero ? 0 : minimum
        }
        activeChanged()
    }

    height          : Variables.progressbarHeight
    touchMargin     : 25

    minimum         : 0
    maximum         : 0

    // real-time bound change should effect the current set value
    onMinimumChanged: {
        if (value < minimum )
            value = minimum
    }
    onMaximumChanged: {
        if (value > maximum )
            value = maximum
    }

    minText {
        visible          : true
        anchors.topMargin: Variables.sliderTextMargin
        font.pixelSize   : Fonts.fontPixelSliderMarker
        font.bold        : false
    }
    maxText {
        visible          : true
        anchors.topMargin: Variables.sliderTextMargin
        font.pixelSize   : Fonts.fontPixelSliderMarker
        font.bold        : false
    }

    function getValueOfX(x) {
        return ( x * ( maximum - minimum ) ) / width + minimum
    }

    function update(vValue) {
        _root.value = vValue
    }

    function setValue(x) {
        let mValue = 0
        let mMinimum = Number(_root.minimum.toFixed(decimal))
        let mMaximum = Number(_root.maximum.toFixed(decimal))
        if ( x <     0 ) { mValue = mMinimum;                           update(mValue); return; }
        if ( x > width ) { mValue = mMaximum;                           update(mValue); return; }

        mValue = getValueOfX(x)

        if ( step === 1 ) { mValue = parseInt(mValue);                  update(mValue); return; }

        let start = 0
        if ( ! stepSnap ) start = mMinimum
        mValue = Math.round((mValue - start) / step) * step + start

        let decimals = Math.round(-Math.log10(step))
        if (decimals > 0) {
            mValue = mValue.toFixed(decimals)
        }

        if ( mValue < mMinimum ) { mValue = mMinimum;                   update(mValue); return; }
        if ( mValue > mMaximum ) { mValue = mMaximum;                   update(mValue); return; }

                                                                        update(mValue); return;
    }

    function setHandlerPosition() {
        if ( _progressRect.width <= 0 ) {
            _handler.x = 0                                          - _root.tickMarksThickness
        } else
        if ( _progressRect.width >= _root.width                     - _root.tickMarksThickness ) {
            _handler.x =            _root.width - _handler.width    + _root.tickMarksThickness
        }
        else {
            _handler.x =    _progressRect.width - _handler.width / 2
        }
    }

    ProgressRect { id: _progressRect
        color       : Colors.highlightProgressBar
        decimal : _root.decimal
        minimum : _root.minimum
        maximum : _root.maximum
        height: 5
        // propagation is not working on drag !
        onDragged: {
            setValue(vMouseEvent.x)
            progressRectDragged()
        }
        onClicked: {
            setValue(vMouseEvent.x)
            progressRectClicked()
        }
        onPressed: {
            setValue(vMouseEvent.x)
            _root.pressed(vMouseEvent)
        }
        onReleased: {
            setValue(vMouseEvent.x)
            _root.released(vMouseEvent)
        }
        onWidthChanged: {
            // TODO: DEN-5603 : Still has some issues on high resolution sliders [ handler jumps to the 0 ].
            // setHandlerPosition()
        }
    }

    // used loader for performance since it may not always be required.
    // and can be a heavy Component
    Loader { id: _ticksLoader
        active          : ticks
        anchors.fill    : parent
        sourceComponent : TickMarks {
            thickness   : _root.tickMarksThickness
            decimal     : _root.decimal
            minimum     : _root.minimum
            maximum     : _root.maximum
            step        : _root.step
            stepSnap    : _root.stepSnap
            textColor   : _root.color
        }
    }

    onDragged: {
        setValue(vMouseEvent.x)
    }
    onClicked: {
        setValue(vMouseEvent.x)
    }
    onPressed: {
        setValue(vMouseEvent.x)
    }
    onReleased: {
        setValue(vMouseEvent.x)
    }

    Rectangle { id: _handler
        property real diameter  : Variables.progressbarHandler

        anchors.verticalCenter  : parent.verticalCenter
        anchors.horizontalCenter: _progressRect.right

        width   : diameter
        height  : diameter
        radius  : diameter
        color   : Colors.highlightProgressBar
        border  {
            width: Variables.progressbarHandlerBorderWidth
            color: Colors.textMain
        }
    }
}
