import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import qs.Commons

/*
NScrollText {
NText {
pointSize: Style.fontSizeS
// here any NText properties can be used
}
maxWidth: 200
text: "Some long long long text"
scrollMode: NScrollText.ScrollMode.Always
}
*/

Item {
  id: root

  required property string text
  default property Component delegate: NText {
    pointSize: Style.fontSizeS
  }

  property real maxWidth: Infinity

  enum ScrollMode {
    Never = 0,
    Always = 1,
    Hover = 2
  }

  property int scrollMode: NScrollText.ScrollMode.Never
  property bool alwaysMaxWidth: false
  property bool forcedHover: false
  property int cursorShape: Qt.ArrowCursor

  property real waitBeforeScrolling: 1000
  property real scrollCycleDuration: Math.max(4000, root.text.length * 120)
  property real resettingDuration: 300

  // Fade controls (fadeExtent: 0.0–0.5, fraction of width that fades)
  property real fadeExtent: 0.1
  property real fadeCornerRadius: 0
  property bool fadeRoundLeftCorners: true

  readonly property real contentWidth: {
    if (!titleText.item)
      return 0;
    const implicit = titleText.item.implicitWidth;
    return implicit > 0 ? implicit : titleText.item.width;
  }
  readonly property real measuredWidth: scrollContainer.width

  implicitWidth: alwaysMaxWidth ? maxWidth : Math.min(maxWidth, contentWidth)
  implicitHeight: titleText.height

  layer.enabled: contentWidth > maxWidth
  layer.effect: MultiEffect {
    maskEnabled: true
    maskThresholdMin: 0.5
    maskSpreadAtMin: 1.0
    maskSource: fadeMask
  }

  enum ScrollState {
    None = 0,
    Scrolling = 1,
    Resetting = 2
  }

  property int state: NScrollText.ScrollState.None

  onTextChanged: {
    if (titleText.item)
      titleText.item.text = text;
    if (loopingText.item)
      loopingText.item.text = text;

    // reset state
    resetState();
  }
  onMaxWidthChanged: resetState()
  onContentWidthChanged: root.updateState()
  onForcedHoverChanged: updateState()

  function resetState() {
    root.state = NScrollText.ScrollState.None;
    scrollContainer.x = 0;
    scrollTimer.restart();
    root.updateState();
  }

  Timer {
    id: scrollTimer
    interval: root.waitBeforeScrolling
    onTriggered: {
      root.state = NScrollText.ScrollState.Scrolling;
      root.updateState();
    }
  }

  MouseArea {
    id: hoverArea
    anchors.fill: parent
    hoverEnabled: true
    acceptedButtons: Qt.NoButton
    onEntered: root.updateState()
    onExited: root.updateState()
    cursorShape: root.cursorShape
  }

  function ensureReset() {
    if (state === NScrollText.ScrollState.Scrolling)
      state = NScrollText.ScrollState.Resetting;
  }

  function updateState() {
    if (contentWidth <= root.maxWidth || scrollMode === NScrollText.ScrollMode.Never) {
      state = NScrollText.ScrollState.None;
      return;
    }
    if (scrollMode === NScrollText.ScrollMode.Always) {
      if (hoverArea.containsMouse) {
        ensureReset();
      } else {
        scrollTimer.restart();
      }
    } else if (scrollMode === NScrollText.ScrollMode.Hover) {
      if (hoverArea.containsMouse || forcedHover)
        state = NScrollText.ScrollState.Scrolling;
      else
        ensureReset();
    }
  }

  RowLayout {
    id: scrollContainer
    height: parent.height
    x: 0
    spacing: 50

    Loader {
      id: titleText
      sourceComponent: root.delegate
      Layout.fillHeight: true
      onLoaded: {
        this.item.text = root.text;
        // Bind height to container to enable vertical centering of overly high text
        this.item.height = Qt.binding(() => titleText.height);
      }
    }

    Loader {
      id: loopingText
      sourceComponent: root.delegate
      Layout.fillHeight: true
      visible: root.state !== NScrollText.ScrollState.None
      onLoaded: {
        this.item.text = root.text;
        this.item.height = Qt.binding(() => loopingText.height);
      }
    }

    NumberAnimation on x {
      running: root.state === NScrollText.ScrollState.Resetting
      to: 0
      duration: root.resettingDuration
      easing.type: Easing.OutQuad
      onFinished: {
        root.state = NScrollText.ScrollState.None;
        root.updateState();
      }
    }

    NumberAnimation on x {
      running: root.state === NScrollText.ScrollState.Scrolling
      to: -(titleText.width + scrollContainer.spacing)
      duration: root.scrollCycleDuration
      loops: Animation.Infinite
      easing.type: Easing.Linear
    }
  }

  // Transparency Fade Rectangle
  Rectangle {
    id: fadeMask
    width: root.width
    height: root.height
    topLeftRadius: fadeRoundLeftCorners ? fadeCornerRadius : 0
    bottomLeftRadius: fadeRoundLeftCorners ? fadeCornerRadius : 0
    topRightRadius: fadeCornerRadius
    bottomRightRadius: fadeCornerRadius
    gradient: Gradient {
      GradientStop {
        position: 0.0
        color: "transparent"
      }
      GradientStop {
        position: fadeExtent
        color: "white"
      }
      GradientStop {
        position: 1 - fadeExtent
        color: "white"
      }
      GradientStop {
        position: 1.0
        color: "transparent"
      }
      orientation: Gradient.Horizontal
    }
    layer.enabled: true
    layer.smooth: true
    opacity: 0
  }
}
