import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Widgets

import qs.Commons
import qs.Services.Compositor
import qs.Services.Hardware
import qs.Services.Media
import qs.Services.Power
import qs.Services.System
import qs.Services.Theming
import qs.Services.UI

Item {
  id: root

  IpcHandler {
    target: "bar"
    function toggle() {
      BarService.isVisible = !BarService.isVisible;
    }
  }

  IpcHandler {
    target: "screenRecorder"
    function toggle() {
      if (ScreenRecorderService.isAvailable) {
        ScreenRecorderService.toggleRecording();
      }
    }
  }

  IpcHandler {
    target: "settings"
    function toggle() {
      root.withTargetScreen(screen => {
                              var settingsPanel = PanelService.getPanel("settingsPanel", screen);
                              settingsPanel?.toggle();
                            });
    }
  }

  IpcHandler {
    target: "calendar"
    function toggle() {
      root.withTargetScreen(screen => {
                              var calendarPanel = PanelService.getPanel("calendarPanel", screen);
                              calendarPanel?.toggle(null, "Clock");
                            });
    }
  }

  IpcHandler {
    target: "notifications"
    function toggleHistory() {
      // Will attempt to open the panel next to the bar button if any.
      root.withTargetScreen(screen => {
                              var notificationHistoryPanel = PanelService.getPanel("notificationHistoryPanel", screen);
                              notificationHistoryPanel.toggle(null, "NotificationHistory");
                            });
    }
    function toggleDND() {
      NotificationService.doNotDisturb = !NotificationService.doNotDisturb;
    }
    function enableDND() {
      NotificationService.doNotDisturb = true;
    }
    function disableDND() {
      NotificationService.doNotDisturb = false;
    }
    function clear() {
      NotificationService.clearHistory();
    }

    function dismissOldest() {
      NotificationService.dismissOldestActive();
    }

    function dismissAll() {
      NotificationService.dismissAllActive();
    }
  }

  IpcHandler {
    target: "idleInhibitor"
    function toggle() {
      return IdleInhibitorService.manualToggle();
    }
  }

  IpcHandler {
    target: "launcher"
    function toggle() {
      root.withTargetScreen(screen => {
                              var launcherPanel = PanelService.getPanel("launcherPanel", screen);
                              launcherPanel?.toggle();
                            });
    }
    function clipboard() {
      root.withTargetScreen(screen => {
                              var launcherPanel = PanelService.getPanel("launcherPanel", screen);
                              launcherPanel?.setSearchText(">clip ");
                              launcherPanel?.toggle();
                            });
    }
    function calculator() {
      root.withTargetScreen(screen => {
                              var launcherPanel = PanelService.getPanel("launcherPanel", screen);
                              launcherPanel?.setSearchText(">calc ");
                              launcherPanel?.toggle();
                            });
    }
    function emoji() {
      root.withTargetScreen(screen => {
                              var launcherPanel = PanelService.getPanel("launcherPanel", screen);
                              launcherPanel?.setSearchText(">emoji ");
                              launcherPanel?.toggle();
                            });
    }
  }

  IpcHandler {
    target: "lockScreen"

    // New preferred method - lock the screen
    function lock() {
      // Only lock if not already locked (prevents the red screen issue)
      if (!PanelService.lockScreen.active) {
        PanelService.lockScreen.active = true;
      }
    }
  }

  IpcHandler {
    target: "brightness"
    function increase() {
      BrightnessService.increaseBrightness();
    }
    function decrease() {
      BrightnessService.decreaseBrightness();
    }
  }

  IpcHandler {
    target: "darkMode"
    function toggle() {
      Settings.data.colorSchemes.darkMode = !Settings.data.colorSchemes.darkMode;
    }
    function setDark() {
      Settings.data.colorSchemes.darkMode = true;
    }
    function setLight() {
      Settings.data.colorSchemes.darkMode = false;
    }
  }

  IpcHandler {
    target: "colorScheme"
    function set(schemeName: string) {
      ColorSchemeService.setPredefinedScheme(schemeName);
    }
  }

  IpcHandler {
    target: "volume"
    function increase() {
      AudioService.increaseVolume();
    }
    function decrease() {
      AudioService.decreaseVolume();
    }
    function muteOutput() {
      AudioService.setOutputMuted(!AudioService.muted);
    }
    function increaseInput() {
      AudioService.increaseInputVolume();
    }
    function decreaseInput() {
      AudioService.decreaseInputVolume();
    }
    function muteInput() {
      AudioService.setInputMuted(!AudioService.inputMuted);
    }
  }

  IpcHandler {
    target: "sessionMenu"
    function toggle() {
      root.withTargetScreen(screen => {
                              var sessionMenuPanel = PanelService.getPanel("sessionMenuPanel", screen);
                              sessionMenuPanel?.toggle();
                            });
    }

    function lockAndSuspend() {
      CompositorService.lockAndSuspend();
    }
  }

  IpcHandler {
    target: "controlCenter"
    function toggle() {
      root.withTargetScreen(screen => {
                              var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen);
                              if (Settings.data.controlCenter.position === "close_to_bar_button") {
                                // Will attempt to open the panel next to the bar button if any.
                                controlCenterPanel?.toggle(null, "ControlCenter");
                              } else {
                                controlCenterPanel?.toggle();
                              }
                            });
    }
  }

  IpcHandler {
    target: "dock"
    function toggle() {
      Settings.data.dock.enabled = !Settings.data.dock.enabled;
    }
  }

  // Wallpaper IPC: trigger a new random wallpaper
  IpcHandler {
    target: "wallpaper"
    function toggle() {
      if (Settings.data.wallpaper.enabled) {
        root.withTargetScreen(screen => {
                                var wallpaperPanel = PanelService.getPanel("wallpaperPanel", screen);
                                wallpaperPanel?.toggle();
                              });
      }
    }

    function random() {
      if (Settings.data.wallpaper.enabled) {
        WallpaperService.setRandomWallpaper();
      }
    }

    function set(path: string, screen: string) {
      if (screen === "all" || screen === "") {
        screen = undefined;
      }
      WallpaperService.changeWallpaper(path, screen);
    }

    function toggleAutomation() {
      Settings.data.wallpaper.randomEnabled = !Settings.data.wallpaper.randomEnabled;
    }
    function disableAutomation() {
      Settings.data.wallpaper.randomEnabled = false;
    }
    function enableAutomation() {
      Settings.data.wallpaper.randomEnabled = true;
    }
  }

  IpcHandler {
    target: "batteryManager"

    function cycle() {
      BatteryService.cycleModes();
    }

    function set(mode: string) {
      switch (mode) {
      case "full":
        BatteryService.setChargingMode(BatteryService.ChargingMode.Full);
        break;
      case "balanced":
        BatteryService.setChargingMode(BatteryService.ChargingMode.Balanced);
        break;
      case "lifespan":
        BatteryService.setChargingMode(BatteryService.ChargingMode.Lifespan);
        break;
      }
    }
  }

  IpcHandler {
    target: "powerProfile"
    function cycle() {
      PowerProfileService.cycleProfile();
    }

    function set(mode: string) {
      switch (mode) {
      case "performance":
        PowerProfileService.setProfile(2);
        break;
      case "balanced":
        PowerProfileService.setProfile(1);
        break;
      case "powersaver":
        PowerProfileService.setProfile(0);
        break;
      }
    }

    function toggleNoctaliaPerformance() {
      PowerProfileService.toggleNoctaliaPerformance();
    }

    function enableNoctaliaPerformance() {
      PowerProfileService.setNoctaliaPerformance(true);
    }

    function disableNoctaliaPerformance() {
      PowerProfileService.setNoctaliaPerformance(false);
    }
  }

  IpcHandler {
    target: "media"
    function playPause() {
      MediaService.playPause();
    }

    function play() {
      MediaService.play();
    }

    function stop() {
      MediaService.stop();
    }

    function pause() {
      MediaService.pause();
    }

    function next() {
      MediaService.next();
    }

    function previous() {
      MediaService.previous();
    }

    function seekRelative(offset: string) {
      var offsetVal = parseFloat(offset);
      if (Number.isNaN(offsetVal)) {
        Logger.w("Media", "Argument to ipc call 'media seekRelative' must be a number");
        return;
      }
      MediaService.seekRelative(offsetVal);
    }

    function seekByRatio(position: string) {
      var positionVal = parseFloat(position);
      if (Number.isNaN(positionVal)) {
        Logger.w("Media", "Argument to ipc call 'media seekByRatio' must be a number");
        return;
      }
      MediaService.seekByRatio(positionVal);
    }
  }

  // Queue an IPC panel operation - will execute when screen is detected
  function withTargetScreen(callback) {
    if (pendingCallback) {
      Logger.w("IPC", "Another IPC call is pending, ignoring new call");
      return;
    }

    // Single monitor setup can execute immediately
    if (Quickshell.screens.length === 1) {
      callback(Quickshell.screens[0]);
    } else {
      // Multi-monitors setup needs to start async detection
      detectedScreen = null;
      pendingCallback = callback;
      screenDetectorLoader.active = true;
    }
  }

  /**
  * For IPC calls on multi-monitors setup that will open panels on screen,
  * we need to open a QS PanelWindow and wait for it's "screen" property to stabilize.
  */
  property ShellScreen detectedScreen: null
  property var pendingCallback: null

  Timer {
    id: screenDetectorDebounce
    running: false
    interval: 20
    onTriggered: {
      Logger.d("IPC", "Screen debounced to:", detectedScreen?.name || "null");

      // Execute pending callback if any
      if (pendingCallback) {
        if (!Settings.data.general.allowPanelsOnScreenWithoutBar) {
          // If we explicitely disabled panels on screen without bar, check if bar is configured
          // for this screen, and fallback to primary screen if necessary
          var monitors = Settings.data.bar.monitors || [];
          const hasBar = monitors.length === 0 || monitors.includes(detectedScreen?.name);
          if (!hasBar) {
            detectedScreen = Quickshell.screens[0];
          }
        }

        Logger.d("IPC", "Executing pending IPC callback on screen:", detectedScreen.name);
        pendingCallback(detectedScreen);
        pendingCallback = null;
      }

      // Clean up
      screenDetectorLoader.active = false;
    }
  }

  // Invisible dummy PanelWindow to detect which screen should receive IPC calls
  Loader {
    id: screenDetectorLoader
    active: false

    sourceComponent: PanelWindow {
      implicitWidth: 0
      implicitHeight: 0
      color: Color.transparent
      WlrLayershell.exclusionMode: ExclusionMode.Ignore
      mask: Region {}

      onScreenChanged: {
        detectedScreen = screen;
        screenDetectorDebounce.restart();
      }
    }
  }
}
