import QtQuick
import QtQuick.Controls
import Quickshell
import qs.Commons
import qs.Modules.Bar.Extras
import qs.Services.Media
import qs.Services.UI
import qs.Widgets
import qs.Widgets.AudioSpectrum

Item {
  id: root

  property ShellScreen screen

  // Widget properties passed from Bar.qml for per-instance settings
  property string widgetId: ""
  property string section: ""
  property int sectionWidgetIndex: -1
  property int sectionWidgetsCount: 0

  // Explicit screenName property ensures reactive binding when screen changes
  readonly property string screenName: screen ? screen.name : ""
  readonly property string barPosition: Settings.getBarPositionForScreen(screenName)
  readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right"
  readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName)

  property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] ?? {}
  property var widgetSettings: {
    if (section && sectionWidgetIndex >= 0 && screenName) {
      var widgets = Settings.getBarWidgetsForScreen(screenName)[section];
      if (widgets && sectionWidgetIndex < widgets.length) {
        return widgets[sectionWidgetIndex];
      }
    }
    return {};
  }

  // Resolve settings: try user settings or defaults from BarWidgetRegistry
  readonly property int visualizerWidth: widgetSettings.width !== undefined ? widgetSettings.width : widgetMetadata.width
  readonly property bool hideWhenIdle: widgetSettings.hideWhenIdle !== undefined ? widgetSettings.hideWhenIdle : widgetMetadata.hideWhenIdle
  readonly property string colorName: widgetSettings.colorName !== undefined ? widgetSettings.colorName : widgetMetadata.colorName

  readonly property color fillColor: Color.resolveColorKey(colorName)

  readonly property bool shouldShow: (currentVisualizerType !== "" && currentVisualizerType !== "none") && (!hideWhenIdle || MediaService.isPlaying)

  // Register/unregister with SpectrumService based on visibility (use screenName — screen can be null after DPMS/output changes)
  readonly property string spectrumComponentId: "bar:audiovisualizer:" + screenName + ":" + root.section + ":" + root.sectionWidgetIndex

  onShouldShowChanged: {
    if (root.shouldShow) {
      SpectrumService.registerComponent(root.spectrumComponentId);
    } else {
      SpectrumService.unregisterComponent(root.spectrumComponentId);
    }
  }

  Component.onDestruction: {
    if (root.shouldShow) {
      SpectrumService.unregisterComponent(root.spectrumComponentId);
    }
  }

  // Content dimensions for implicit sizing
  readonly property real contentWidth: !shouldShow ? 0 : isVerticalBar ? capsuleHeight : visualizerWidth
  readonly property real contentHeight: !shouldShow ? 0 : isVerticalBar ? visualizerWidth : capsuleHeight

  implicitWidth: contentWidth
  implicitHeight: contentHeight
  visible: shouldShow
  opacity: shouldShow ? 1.0 : 0.0

  Behavior on implicitWidth {
    NumberAnimation {
      duration: Style.animationNormal
      easing.type: Easing.InOutCubic
    }
  }
  Behavior on implicitHeight {
    NumberAnimation {
      duration: Style.animationNormal
      easing.type: Easing.InOutCubic
    }
  }

  // Store visualizer type to force re-evaluation
  readonly property string currentVisualizerType: Settings.data.audio.visualizerType

  // Visual capsule centered in parent
  Rectangle {
    id: background
    width: root.contentWidth
    height: root.contentHeight
    anchors.centerIn: parent
    radius: Style.radiusS
    color: Style.capsuleColor
    border.color: Style.capsuleBorderColor
    border.width: Style.capsuleBorderWidth

    // When visualizer type or playback changes, shouldShow updates automatically
    // The Loader dynamically loads the appropriate visualizer based on settings
    Loader {
      id: visualizerLoader
      anchors.fill: parent
      anchors.margins: Style.marginS
      active: shouldShow
      asynchronous: true

      sourceComponent: {
        switch (currentVisualizerType) {
        case "linear":
          return linearComponent;
        case "mirrored":
          return mirroredComponent;
        case "wave":
          return waveComponent;
        default:
          return null;
        }
      }
    }
  }

  NPopupContextMenu {
    id: contextMenu

    model: [
      {
        "label": I18n.tr("actions.cycle-visualizer"),
        "action": "cycle-visualizer",
        "icon": "chart-column"
      },
      {
        "label": I18n.tr("actions.widget-settings"),
        "action": "widget-settings",
        "icon": "settings"
      },
    ]

    onTriggered: action => {
                   contextMenu.close();
                   if (screen) {
                     PanelService.closeContextMenu(screen);
                   }

                   if (action === "cycle-visualizer") {
                     const types = ["linear", "mirrored", "wave"];
                     const currentIndex = types.indexOf(currentVisualizerType);
                     const nextIndex = (currentIndex + 1) % types.length;
                     Settings.data.audio.visualizerType = types[nextIndex];
                   } else if (action === "widget-settings" && screen) {
                     BarService.openWidgetSettings(screen, section, sectionWidgetIndex, widgetId, widgetSettings);
                   }
                 }
  }

  // Click to cycle through visualizer types
  MouseArea {
    id: mouseArea
    anchors.fill: parent
    cursorShape: Qt.PointingHandCursor
    hoverEnabled: true
    acceptedButtons: Qt.LeftButton | Qt.RightButton

    onClicked: mouse => {
                 if (mouse.button === Qt.RightButton) {
                   if (screen) {
                     PanelService.showContextMenu(contextMenu, root, screen);
                   }
                 } else {
                   const types = ["linear", "mirrored", "wave"];
                   const currentIndex = types.indexOf(currentVisualizerType);
                   const nextIndex = (currentIndex + 1) % types.length;
                   Settings.data.audio.visualizerType = types[nextIndex];
                 }
               }
  }

  Component {
    id: linearComponent
    NLinearSpectrum {
      anchors.fill: parent
      values: SpectrumService.values
      fillColor: root.fillColor
      showMinimumSignal: true
      vertical: root.isVerticalBar
      barPosition: root.barPosition
      mirrored: Settings.data.audio.spectrumMirrored
    }
  }

  Component {
    id: mirroredComponent
    NMirroredSpectrum {
      anchors.fill: parent
      values: SpectrumService.values
      fillColor: root.fillColor
      showMinimumSignal: true
      vertical: root.isVerticalBar
      mirrored: Settings.data.audio.spectrumMirrored
    }
  }

  Component {
    id: waveComponent
    NWaveSpectrum {
      anchors.fill: parent
      values: SpectrumService.values
      fillColor: root.fillColor
      showMinimumSignal: true
      vertical: root.isVerticalBar
      mirrored: Settings.data.audio.spectrumMirrored
    }
  }
}
