local _, ns = ...

local VALID_SIDEBAR_SORT_MODES = {
    name = true,
    level = true,
    itemLevel = true,
    priority = true,
}

local DEFAULT_WINDOW_POSITION = {
    point = "CENTER",
    relativePoint = "CENTER",
    x = 0,
    y = 0,
}

local function normalizeSidebarSortMode(sortMode)
    if type(sortMode) ~= "string" or sortMode == "" or not VALID_SIDEBAR_SORT_MODES[sortMode] then
        return nil
    end
    return sortMode
end

function ns:GetSidebarSortMode()
    local mode = normalizeSidebarSortMode(self.db and self.db.ui and self.db.ui.sidebarSortMode)
    if self.db and self.db.ui then
        self.db.ui.sidebarSortMode = mode
    end
    return mode
end

function ns:SetSidebarSortMode(sortMode, skipRefresh)
    if not self.db or not self.db.ui then
        return nil
    end

    local mode = normalizeSidebarSortMode(sortMode)
    self.db.ui.sidebarSortMode = mode
    if self.UI then
        self.UI.sidebarSortMode = mode
    end
    if skipRefresh ~= true then
        if self.UI and self.UI.RefreshSidebar then
            self.UI:RefreshSidebar()
        elseif self.UI and self.UI.Refresh then
            self.UI:Refresh()
        end
    end
    return mode
end

function ns:GetScalePercent()
    return self.db and self.db.ui and tonumber(self.db.ui.scalePercent) or 100
end

function ns:SetScalePercent(value)
    if not self.db or not self.db.ui then
        return
    end

    self.db.ui.scalePercent = math.max(70, math.min(125, math.floor(tonumber(value) or 100)))
    if self.UI and self.UI.Refresh then
        self.UI:Refresh()
    end
end

function ns:GetOpacityPercent()
    return self.db and self.db.ui and tonumber(self.db.ui.opacityPercent) or 100
end

function ns:SetOpacityPercent(value)
    if not self.db or not self.db.ui then
        return
    end

    self.db.ui.opacityPercent = math.max(65, math.min(100, math.floor(tonumber(value) or 100)))
    if self.UI and self.UI.Refresh then
        self.UI:Refresh()
    end
end

function ns:GetWindowPosition()
    if (not self.db or not self.db.ui) and self.EnsureDB then
        self:EnsureDB()
    end

    local position = self.db and self.db.ui and self.db.ui.windowPosition or nil
    if type(position) ~= "table" then
        position = DEFAULT_WINDOW_POSITION
    end

    return {
        point = type(position.point) == "string" and position.point or DEFAULT_WINDOW_POSITION.point,
        relativePoint = type(position.relativePoint) == "string" and position.relativePoint or DEFAULT_WINDOW_POSITION.relativePoint,
        x = tonumber(position.x) or DEFAULT_WINDOW_POSITION.x,
        y = tonumber(position.y) or DEFAULT_WINDOW_POSITION.y,
    }
end

function ns:SetWindowPosition(point, relativePoint, x, y)
    if (not self.db or not self.db.ui) and self.EnsureDB then
        self:EnsureDB()
    end
    if not self.db or not self.db.ui then
        return false
    end

    self.db.ui.windowPosition = {
        point = type(point) == "string" and point or DEFAULT_WINDOW_POSITION.point,
        relativePoint = type(relativePoint) == "string" and relativePoint or DEFAULT_WINDOW_POSITION.relativePoint,
        x = tonumber(x) or DEFAULT_WINDOW_POSITION.x,
        y = tonumber(y) or DEFAULT_WINDOW_POSITION.y,
    }
    return true
end

function ns:StoreWindowPosition(frame)
    if not frame or type(frame.GetPoint) ~= "function" then
        return false
    end

    local point, _, relativePoint, x, y = frame:GetPoint(1)
    if not point then
        return false
    end
    return self:SetWindowPosition(point, relativePoint or point, x, y)
end

function ns:ResetWindowPosition()
    if (not self.db or not self.db.ui) and self.EnsureDB then
        self:EnsureDB()
    end
    if self.db and self.db.ui then
        self.db.ui.windowPosition = nil
    end
    if self.UI and self.UI.ApplyWindowPosition then
        self.UI:ApplyWindowPosition()
    end
    return true
end

function ns:IsMinimapHidden()
    local minimap = self.db and self.db.ui and self.db.ui.minimap
    return minimap and (minimap.hide == true or minimap.hidden == true) or false
end

function ns:SetMinimapHidden(hidden)
    if not self.db or not self.db.ui then
        return
    end

    self.db.ui.minimap = self.db.ui.minimap or {}
    self.db.ui.minimap.hide = hidden == true
    self.db.ui.minimap.hidden = hidden == true
    if self.UI and self.UI.RefreshMinimapButton then
        self.UI:RefreshMinimapButton()
    end
    if self.UI and self.UI.Refresh then
        self.UI:Refresh()
    end
end

function ns:GetMinimapAngle()
    local minimap = self.db and self.db.ui and self.db.ui.minimap
    return minimap and tonumber(minimap.minimapPos or minimap.angle) or 225
end

function ns:SetMinimapAngle(angle)
    if not self.db or not self.db.ui then
        return
    end

    self.db.ui.minimap = self.db.ui.minimap or {}
    self.db.ui.minimap.minimapPos = tonumber(angle) or 225
    self.db.ui.minimap.angle = tonumber(self.db.ui.minimap.minimapPos) or 225
    if self.UI and self.UI.UpdateMinimapPosition then
        self.UI:UpdateMinimapPosition()
    end
end

function ns:IsAltScoreHidden()
    return self.db and self.db.ui and self.db.ui.altScoreHidden == true
end

function ns:SetAltScoreHidden(hidden)
    if not self.db or not self.db.ui then
        return
    end

    self.db.ui.altScoreHidden = hidden == true
    if self.ClearAltPriorityScoreCache then
        self:ClearAltPriorityScoreCache()
    end
    if self.UI and self.UI.Refresh then
        self.UI:Refresh()
    end
end
