-- read namespace from global env
local _G = _G
local Grichelde = _G.Grichelde

local pairs, tInsert, tClone, unpack, join, toString
    = Grichelde.functions.pairs, Grichelde.functions.tInsert, Grichelde.functions.tClone, Grichelde.functions.unpack, Grichelde.functions.join, Grichelde.functions.toString

function Grichelde:GetDefaultConfig()
    return {
        global = {},
        profile = {
            enabled = true,
            channels = {
                ["*"] = false,
                say = true,
                emote = false,
                yell = true,
                party = true,
                guild = true,
                officer = true,
            },
            replacements = {
                ["**"] = {
                    order = 9999,
                    searchText = "",
                    replaceText = "",
                    exactCase = false,
                    consolidate = true,
                },
                replacement_10 = {
                    order = 10,
                    searchText = "s",
                    replaceText = "ch",
                    exactCase = false,
                    consolidate = true,
                },
                replacement_11 = {
                    order = 11,
                    searchText = "t",
                    replaceText = "ck",
                    exactCase = false,
                    consolidate = true,
                },
                replacement_12 = {
                    order = 12,
                    searchText = "Zark",
                    replaceText = "toter Schamane",
                    exactCase = false,
                    consolidate = true,
                }
            }
        }
    }
end

function Grichelde:LoadDatabase()
    local db = LibStub("AceDB-3.0"):New(self.name .."DB", self:GetDefaultConfig(), true)

    db.RegisterCallback(self, "OnNewProfile", "RefreshOptions")
    db.RegisterCallback(self, "OnProfileChanged", "RefreshOptions")
    db.RegisterCallback(self, "OnProfileDeleted", "RefreshOptions")
    db.RegisterCallback(self, "OnProfileCopied", "RefreshOptions")
    db.RegisterCallback(self, "OnProfileReset", "RefreshOptions")

    return db
end

function Grichelde:SyncToDatabase(info, val)
    self:TracePrint("SyncToDatabase : info")
    for i = 0, #info do
        self:TracePrint("%d = %s", i, info[i])
    end

    local option = self.db.profile
    local path = 1
    while (path < #info) do
        if info[path] ~= "mappings" then
            option = option[info[path]] -- or nil
        end
        path = path + 1
    end
    local optionPath = join(".", unpack(info, 1, #info))
    self:DebugPrint("change option \"%s\" from %s to %s", optionPath, toString(option[info[path]]), toString(val))
    option[info[path]] = val
end

function Grichelde:ReadFromDatabase(info)
    self:TracePrint("ReadFromDatabase : info")
    for i = 0, #info do
        self:TracePrint("%d = %s", i, info[i])
    end

    local option = self.db.profile
    local path = 1
    while (path <= #info) do
        if info[path] ~= "mappings" then
            option = option[info[path]] -- or nil
        end
        path = path + 1
    end
    local optionPath = join(".", unpack(info, 1, #info))
    self:DebugPrint("read option \"%s\": %s", optionPath, toString(option))
    return option
end

--- Sorts a replacements table by order sub-field and rename.
--- Do NOT reassign self.db.profile.replacements here or with its output as it will break defaults
function Grichelde:ReorderReplacements()
    local replacements = self.db.profile.replacements or {}

    self:TracePrint("ReorderReplacements : unsorted table")
    self:TracePrint(replacements)

    local orderToName = {}
    local size = 0
    for replName, replTable in pairs(replacements) do
        size = size + 1
        tInsert(orderToName, replTable.order, replName)
    end

    self:TracePrint("ReorderReplacements : size: %d, orderToName", size)
    self:TracePrint(orderToName)

    local sorted = {}
    local index, count = 0, 0

    while count < size do
        local replName = orderToName[index]
        if replName and replacements[replName] then
            self:TracePrint("ReorderReplacements : replName: %s, replTable", replName)
            self:TracePrint(replacements[replName])
            local order = Grichelde.MAPPING_OFFSET + count
            sorted["replacement_" .. order] = tClone(replacements[replName])
            sorted["replacement_" .. order].order = order
            count = count + 1
        end
        index = index + 1
        if ( index > 10000) then break end
    end

--  self:TracePrint("ReorderReplacements : sorted")
--  self:TracePrint(sorted)

    -- do NOT set self.db.profile.replacements = {} it will break defaults
    for replName, _ in pairs(replacements) do
        replacements[replName] = nil
    end

    -- copy over sorted replacements
    for replName, replTable in pairs(sorted) do
        replacements[replName] = replTable
    end

    self:DebugPrint("ReorderReplacements : sorted table")
    self:DebugPrint(self.db.profile.replacements)
end