import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Commons
import qs.Services.UI

Item {
  id: root

  required property ShellScreen screen

  // Local queue for this screen only (bounded to prevent memory issues)
  property var messageQueue: []
  property int maxQueueSize: 10
  property bool isShowingToast: false

  // If true, immediately show new toasts
  property bool replaceOnNew: true

  Connections {
    target: ToastService

    function onNotify(message, description, icon, type, duration) {
      root.enqueueToast({
                          "message": message,
                          "description": description,
                          "icon": icon,
                          "type": type,
                          "duration": duration,
                          "timestamp": Date.now()
                        })
    }
  }

  // Clear queue on component destruction to prevent orphaned toasts
  Component.onDestruction: {
    messageQueue = []
    isShowingToast = false
    hideTimer.stop()
    quickSwitchTimer.stop()
  }

  function enqueueToast(toastData) {
    // Safe logging - fix the substring bug
    var descPreview = (toastData.description || "").substring(0, 100).replace(/\n/g, " ")
    Logger.i("ToastScreen", "Queuing", toastData.type, ":", toastData.message, descPreview)

    // Bounded queue to prevent unbounded memory growth
    if (messageQueue.length >= maxQueueSize) {
      Logger.i("ToastScreen", "Queue full, dropping oldest toast")
      messageQueue.shift()
    }

    if (replaceOnNew && isShowingToast) {
      // Cancel current toast and clear queue for latest toast
      messageQueue = [] // Clear existing queue
      messageQueue.push(toastData)

      // Hide current toast immediately
      if (windowLoader.item) {
        hideTimer.stop()
        windowLoader.item.hideToast()
      }

      // Process new toast after a brief delay
      isShowingToast = false
      quickSwitchTimer.restart()
    } else {
      // Queue the toast
      messageQueue.push(toastData)
      processQueue()
    }
  }

  Timer {
    id: quickSwitchTimer
    interval: 50 // Brief delay for smooth transition
    onTriggered: root.processQueue()
  }

  function processQueue() {
    if (messageQueue.length === 0 || isShowingToast) {
      return
    }

    var data = messageQueue.shift()
    isShowingToast = true

    // Store the toast data for when loader is ready
    windowLoader.pendingToast = data

    // Activate the loader - onStatusChanged will handle showing the toast
    windowLoader.active = true
  }

  function onToastHidden() {
    isShowingToast = false

    // Deactivate the loader to completely remove the window and free memory
    windowLoader.active = false

    // Small delay before processing next toast
    hideTimer.restart()
  }

  Timer {
    id: hideTimer
    interval: 200
    onTriggered: root.processQueue()
  }

  // The loader that creates/destroys the PanelWindow as needed
  // This is good for RAM efficiency when toasts are infrequent
  Loader {
    id: windowLoader
    active: false // Only active when showing a toast

    // Store pending toast data
    property var pendingToast: null

    onStatusChanged: {
      // When loader becomes ready, show the pending toast
      if (status === Loader.Ready && pendingToast !== null) {
        item.showToast(pendingToast.message, pendingToast.description, pendingToast.icon, pendingToast.type, pendingToast.duration)
        pendingToast = null
      }
    }

    sourceComponent: PanelWindow {
      id: panel

      property alias toastItem: toastItem

      screen: root.screen

      // Parse location setting
      readonly property string location: Settings.data.notifications?.location || "top_right"
      readonly property bool isTop: location.startsWith("top")
      readonly property bool isBottom: location.startsWith("bottom")
      readonly property bool isLeft: location.endsWith("_left")
      readonly property bool isRight: location.endsWith("_right")
      readonly property bool isCentered: location === "top" || location === "bottom"

      readonly property string barPos: Settings.data.bar.position
      readonly property bool isFloating: Settings.data.bar.floating

      // Calculate bar offsets for each edge separately
      readonly property int barOffsetTop: {
        if (barPos !== "top")
          return 0
        const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0
        return Style.barHeight + floatMarginV
      }

      readonly property int barOffsetBottom: {
        if (barPos !== "bottom")
          return 0
        const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0
        return Style.barHeight + floatMarginV
      }

      readonly property int barOffsetLeft: {
        if (barPos !== "left")
          return 0
        const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0
        return floatMarginH
      }

      readonly property int barOffsetRight: {
        if (barPos !== "right")
          return 0
        const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0
        return floatMarginH
      }

      // Anchoring
      anchors.top: isTop
      anchors.bottom: isBottom
      anchors.left: isLeft
      anchors.right: isRight

      // Margins for PanelWindow - only apply bar offset for the specific edge where the bar is
      margins.top: isTop ? barOffsetTop : 0
      margins.bottom: isBottom ? barOffsetBottom : 0
      margins.left: isLeft ? barOffsetLeft : 0
      margins.right: isRight ? barOffsetRight : 0

      implicitWidth: Math.round(toastItem.width)
      implicitHeight: Math.round(toastItem.height)

      color: Color.transparent

      WlrLayershell.layer: (Settings.data.notifications && Settings.data.notifications.overlayLayer) ? WlrLayer.Overlay : WlrLayer.Top
      WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
      WlrLayershell.exclusionMode: ExclusionMode.Ignore

      //mask: Region {}
      function showToast(message, description, icon, type, duration) {
        toastItem.show(message, description, icon, type, duration)
      }

      function hideToast() {
        toastItem.hideImmediately()
      }

      SimpleToast {
        id: toastItem
        onHidden: root.onToastHidden()
      }
    }
  }
}
