-- read namespace from global env
local _G = _G
local Grichelde = _G.Grichelde or {}

local pairs, tInsert, tClone, tWipe, unpack, join, toString
    = Grichelde.F.pairs, Grichelde.F.tInsert, Grichelde.F.tClone, Grichelde.F.tWipe, Grichelde.F.unpack, Grichelde.F.join, Grichelde.F.toString

function Grichelde.getDefaultConfig()
    return {
        global = {},
        profile = {
            enabled = true,
            minimapButton = {
                hide = false
            },
            channels = {
                ["*"] = false,
                say = true,
                emote = false,
                yell = true,
                party = true,
                guild = true,
                officer = true,
            },
            replacements = {
                ["**"] = {
                    order = 999,
                    searchText = "",
                    replaceText = "",
                    exactCase = false,
                    consolidate = true,
                    matchWhen = 2,
                    stopOnMatch = false,
                },
            }
        }
    }
end

function Grichelde.getDefaultSampleMappings()
    return {
        replacement_10 = {
            order = 10,
            searchText = "s",
            replaceText = "ch",
            exactCase = false,
            consolidate = true,
            matchWhen = 2,
            stopOnMatch = false,
        },
        replacement_11 = {
            order = 11,
            searchText = "t",
            replaceText = "ck",
            exactCase = false,
            consolidate = true,
            matchWhen = 2,
            stopOnMatch = false,
        },
        replacement_12 = {
            order = 12,
            searchText = "p",
            replaceText = "b",
            exactCase = false,
            consolidate = true,
            matchWhen = 2,
            stopOnMatch = false,
        }
    }
end

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

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

    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]]
        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]]
        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(replacements)
    local repls = replacements or self.db.profile.replacements or {}

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

    local orderToName = {}
    local size = 0
    for replName, replTable in pairs(repls) 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 ~= nil) and (repls[replName] ~= nil) then
            self:TracePrint("ReorderReplacements : replName: %s, replTable", replName)
            self:TracePrint(repls[replName])
            local order = Grichelde.MAPPING_OFFSET + count
            sorted["replacement_" .. order] = tClone(repls[replName])
            sorted["replacement_" .. order].order = order
            count = count + 1
        end
        index = index + 1
        if (index > 999) then break end
    end

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