import QtQuick
import QtQuick.Effects
import Quickshell
import qs.Commons
import qs.Modules.DesktopWidgets
import qs.Services.Media
import qs.Services.UI
import qs.Widgets
import qs.Widgets.AudioSpectrum

DraggableDesktopWidget {
  id: root

  defaultY: 280

  readonly property var widgetMetadata: DesktopWidgetRegistry.widgetMetadata["AudioVisualizer"]

  readonly property int visualizerWidth: (widgetData && widgetData.width !== undefined) ? widgetData.width : (widgetMetadata?.width ?? 320)
  readonly property int visualizerHeight: (widgetData && widgetData.height !== undefined) ? widgetData.height : (widgetMetadata?.height ?? 72)
  readonly property string visualizerType: (widgetData && widgetData.visualizerType !== undefined) ? widgetData.visualizerType : (widgetMetadata?.visualizerType ?? "linear")
  readonly property bool hideWhenIdle: (widgetData && widgetData.hideWhenIdle !== undefined) ? widgetData.hideWhenIdle : (widgetMetadata?.hideWhenIdle ?? false)
  readonly property string colorName: (widgetData && widgetData.colorName !== undefined) ? widgetData.colorName : (widgetMetadata?.colorName ?? "primary")

  readonly property color fillColor: Color.resolveColorKey(colorName)

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

  // Keep widget visible in edit mode so users can move/configure it
  visible: !root.isHidden || DesktopWidgetRegistry.editMode

  readonly property string spectrumComponentId: "desktop:audiovisualizer:" + (root.screen ? root.screen.name : "unknown") + ":" + root.widgetIndex

  onShouldRegisterSpectrumChanged: {
    if (root.shouldRegisterSpectrum) {
      SpectrumService.registerComponent(root.spectrumComponentId);
    } else {
      SpectrumService.unregisterComponent(root.spectrumComponentId);
    }
  }

  Component.onCompleted: {
    if (root.shouldRegisterSpectrum) {
      SpectrumService.registerComponent(root.spectrumComponentId);
    }
  }

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

  implicitWidth: Math.round(visualizerWidth * widgetScale)
  implicitHeight: Math.round(visualizerHeight * widgetScale)
  width: implicitWidth
  height: implicitHeight

  Rectangle {
    id: visualizerMask
    anchors.fill: parent
    color: "transparent"
    radius: root.roundedCorners ? Math.min(Math.round(Style.radiusL * root.widgetScale), Style.radiusL, width / 2, height / 2) : 0
    clip: true

    Loader {
      id: visualizerLoader
      anchors.fill: parent
      anchors.margins: root.showBackground ? Math.round(Style.marginXS * root.widgetScale) : 0
      active: root.shouldShow
      asynchronous: true

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

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

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

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