pragma Singleton

import QtQuick
import Quickshell
import qs.Commons

Singleton {
  id: root

  // Cache for current scales - updated via signals
  property var currentScales: ({})

  // Signal emitted when scale changes
  signal scaleChanged(string screenName, real scale)

  Component.onCompleted: {
    Logger.log("Scaling", "Service started")
  }

  Connections {
    target: Settings
    function onSettingsLoaded() {
      // Initialize cache from Settings once they are loaded on startup
      var monitors = Settings.data.ui.monitorsScaling || []
      for (var i = 0; i < monitors.length; i++) {
        if (monitors[i].name && monitors[i].scale !== undefined) {
          currentScales[monitors[i].name] = monitors[i].scale
          root.scaleChanged(monitors[i].name, monitors[i].scale)
          Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale)
        }
      }
    }
  }

  // -------------------------------------------
  // Manual scaling via Settings
  function getScreenScale(aScreen) {
    try {
      if (aScreen !== undefined && aScreen.name !== undefined) {
        return getScreenScaleByName(aScreen.name)
      }
    } catch (e) {

      //Logger.warn(e)
    }
    return 1.0
  }

  // -------------------------------------------
  // Get scale from cache for better performance
  function getScreenScaleByName(aScreenName) {
    try {
      var scale = currentScales[aScreenName]
      if ((scale !== undefined) && (scale != null)) {
        return scale
      }
    } catch (e) {

      //Logger.warn(e)
    }
    return 1.0
  }

  // -------------------------------------------
  function setScreenScale(aScreen, scale) {
    try {
      if (aScreen !== undefined && aScreen.name !== undefined) {
        return setScreenScaleByName(aScreen.name, scale)
      }
    } catch (e) {

      //Logger.warn(e)
    }
  }

  // -------------------------------------------
  function setScreenScaleByName(aScreenName, scale) {
    try {
      // Check if scale actually changed
      var oldScale = currentScales[aScreenName] || 1.0
      if (oldScale === scale) {
        return
        // No change needed
      }

      // Update cache directly
      currentScales[aScreenName] = scale

      // Update Settings with immutable update for proper persistence
      var monitors = Settings.data.ui.monitorsScaling || []
      var found = false

      var newMonitors = monitors.map(function (monitor) {
        if (monitor.name === aScreenName) {
          found = true
          return {
            "name": aScreenName,
            "scale": scale
          }
        }
        return monitor
      })

      if (!found) {
        newMonitors.push({
                           "name": aScreenName,
                           "scale": scale
                         })
      }

      // Use slice() to ensure Settings detects the change
      Settings.data.ui.monitorsScaling = newMonitors.slice()

      // Emit signal for components to react
      root.scaleChanged(aScreenName, scale)

      Logger.log("Scaling", "Scale changed for", aScreenName, "to", scale)
    } catch (e) {
      Logger.warn("Scaling", "Error setting scale:", e)
    }
  }

  // -------------------------------------------
  // Dynamic scaling based on resolution
  // Design reference resolution (for scale = 1.0)
  readonly property int designScreenWidth: 2560
  readonly property int designScreenHeight: 1440
  function dynamicScale(aScreen) {
    if (aScreen != null) {
      var ratioW = aScreen.width / designScreenWidth
      var ratioH = aScreen.height / designScreenHeight
      return Math.min(ratioW, ratioH)
    }
    return 1.0
  }
}
