MS_GridManager = MS_GridManager or {}

local DEFAULT_GRID_SIZE = 10
local MIN_GRID_SIZE = 1
local MAX_GRID_SIZE = 50

-- Provide a single source of truth for the optional drag-to-grid feature.
function MS_GridManager.getDefaultSettings()
    return {
        enabled = false,
        sizeX = DEFAULT_GRID_SIZE,
        sizeY = DEFAULT_GRID_SIZE,
    }
end

local function _sanitizeSize(value, fallback)
    local numberValue = tonumber(value)
    if not numberValue then
        numberValue = fallback or DEFAULT_GRID_SIZE
    end

    -- Clamp persisted values so old configs cannot escape the new UI limits.
    numberValue = math.floor(numberValue)
    if numberValue < MIN_GRID_SIZE then
        numberValue = MIN_GRID_SIZE
    elseif numberValue > MAX_GRID_SIZE then
        numberValue = MAX_GRID_SIZE
    end

    return numberValue
end

local function _normalizeGridSettings(settings)
    local defaults = MS_GridManager.getDefaultSettings()
    settings = settings or {}

    if settings.enabled == nil then
        settings.enabled = defaults.enabled
    end

    settings.sizeX = _sanitizeSize(settings.sizeX, defaults.sizeX)
    settings.sizeY = _sanitizeSize(settings.sizeY, defaults.sizeY)
    return settings
end

function MS_GridManager.getSettings(playerIndex)
    local globalConfig = MSConfig.getGlobalConfig(playerIndex)
    local storedSettings = globalConfig.gridSettings
    local normalized = _normalizeGridSettings(storedSettings)

    -- Persist lazily so older configs gain the new keys without breaking compatibility.
    if storedSettings == nil
        or storedSettings.enabled == nil
        or storedSettings.sizeX ~= normalized.sizeX
        or storedSettings.sizeY ~= normalized.sizeY then
        MSConfig.updateGlobalConfig(playerIndex, "gridSettings", normalized)
    end

    return normalized
end

function MS_GridManager.isEnabled(playerIndex)
    return MS_GridManager.getSettings(playerIndex).enabled == true
end

function MS_GridManager.setEnabled(playerIndex, enabled)
    local settings = MS_GridManager.getSettings(playerIndex)
    settings.enabled = enabled == true
    MSConfig.updateGlobalConfig(playerIndex, "gridSettings", settings)
    return settings
end

function MS_GridManager.setSize(playerIndex, sizeX, sizeY)
    local settings = MS_GridManager.getSettings(playerIndex)
    settings.sizeX = _sanitizeSize(sizeX, settings.sizeX)
    settings.sizeY = _sanitizeSize(sizeY, settings.sizeY)
    MSConfig.updateGlobalConfig(playerIndex, "gridSettings", settings)
    return settings
end

function MS_GridManager.getDisplaySize(playerIndex)
    local settings = MS_GridManager.getSettings(playerIndex)
    return settings.sizeX, settings.sizeY
end

function MS_GridManager.formatSizeLabel(playerIndex)
    local sizeX, sizeY = MS_GridManager.getDisplaySize(playerIndex)
    return tostring(sizeX) .. "," .. tostring(sizeY)
end

local function _snapValue(value, step)
    local sanitizedStep = _sanitizeSize(step, 10)
    return math.floor((value / sanitizedStep) + 0.5) * sanitizedStep
end

function MS_GridManager.snapPosition(playerIndex, x, y)
    local settings = MS_GridManager.getSettings(playerIndex)
    return _snapValue(x, settings.sizeX), _snapValue(y, settings.sizeY)
end

function MS_GridManager.getToggleSuffix(playerIndex)
    if MS_GridManager.isEnabled(playerIndex) then
        return getText("IGUI_ModernStatus_on")
    end
    return getText("IGUI_ModernStatus_Off")
end

return MS_GridManager
