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

local pairs, tSize, tClone, find, sub, cGreen, cOrange, cRed, toNumber
    = Grichelde.F.pairs, Grichelde.F.tSize,Grichelde.F.tClone, Grichelde.F.find, Grichelde.F.sub, Grichelde.F.cGreen, Grichelde.F.cOrange, Grichelde.F.cRed, Grichelde.F.toNumber

function Grichelde:Upgrade_To_v060()
    self:PrefixedPrint(self.L.Upgrade_ToVersion, cOrange("0.6.0"))

    local replacements = self.db.profile.replacements or {}
    self:DebugPrint("Upgrade_To_v060 : old database")
    self:DebugPrint(replacements)

    for _, replTable in pairs(replacements) do
        replTable["ignoreCase"] = not replTable["caseSensitive"]
        replTable["caseSensitive"] = nil
    end

    self:DebugPrint("Upgrade_To_v060 : new database")
    self:DebugPrint(replacements)
    return 0, 6, 0
end

function Grichelde:Upgrade_To_v070()
    self:PrefixedPrint(self.L.Upgrade_ToVersion, cOrange("0.7.0"))

    local replacements = self.db.profile.replacements or {}
    self:DebugPrint("Upgrade_To_v070 : old replacements")
    self:DebugPrint(replacements)

    for _, replTable in pairs(replacements) do
        replTable["exactCase"] = not replTable["ignoreCase"]
        replTable["ignoreCase"] = nil
    end

    self:DebugPrint("Upgrade_To_v070 : new replacements")
    self:DebugPrint(replacements)
    return 0, 7, 0
end

function Grichelde:Upgrade_To_v072()
    self:PrefixedPrint(self.L.Upgrade_ToVersion, cOrange("0.7.2"))

    self:DebugPrint("Upgrade_To_v072 : old database")
    self:DebugPrint(self.db.profile)

    self.db.profile["minimapButton"] = { hide = false }

    self:DebugPrint("Upgrade_To_v072 : new database")
    self:DebugPrint(self.db.profile)
    return 0, 7, 2
end

function Grichelde:Upgrade_To_v080()
    self:PrefixedPrint(self.L.Upgrade_ToVersion, cOrange("0.8.0"))

    local replacements = self.db.profile.replacements or {}
    self:DebugPrint("Upgrade_To_v080 : old replacements")
    self:DebugPrint(replacements)

    for _, replTable in pairs(replacements) do
        replTable["active"] = true
    end

    self:DebugPrint("Upgrade_To_v080 : new replacements")
    self:DebugPrint(self.db.profile)
    return 0, 8, 0
end

function Grichelde:Upgrade_To_v090()
    self:PrefixedPrint(self.L.Upgrade_ToVersion, cOrange("0.9.0"))

    local replacements = self.db.profile.replacements or {}
    self:DebugPrint("Upgrade_To_v090 : old replacements")
    self:DebugPrint(replacements)

    for _, replTable in pairs(replacements) do
        if (replTable["active"] == true) then
            replTable["matchWhen"] = 2
        else
            replTable["matchWhen"] = 1
        end
        replTable["active"] = nil
    end

    self:DebugPrint("Upgrade_To_v090 : new replacements")
    self:DebugPrint(self.db.profile)
    return 0, 9, 0
end

function Grichelde:UpgradeDatabase()
    local function parseVersion(version)
        local _, _, major, minor, patch, ext = find(version, "(%d+)%.(%d+)%.(%d+)(.*)")
        local preBuild, build = ext, ""
        if (sub(ext, 1, 1) == "-") then
            local b = find(ext, "+", 2)
            if (b ~= nil) then
                preBuild = sub(ext, 1, b)
                build = sub(ext, b + 1)
            else
                preBuild = sub(ext, 1, b)
            end
        end
        return toNumber(major) or 0, toNumber(minor) or 0, toNumber(patch) or 0, preBuild, build
    end

    local gMajor, gMinor, gPatch = parseVersion(self.version)
    local dbVersion = self.db.global.version

    if (dbVersion == nil) then
        self:DebugPrint("New installation detected, add sample mappings")
        -- do NOT set self.db.profile.replacements = {} it will break defaults
        local sampleRepl = self.getDefaultSampleMappings()
        for replName, replTable in pairs(sampleRepl) do
            self:TracePrint("UpgradeDatabase : copySampleMappings %s", replName)
            self.db.profile.replacements[replName] = tClone(replTable)
        end

        self.db.global.version = self:Format("%d.%d.%d", gMajor, gMinor, gPatch)
        self:DebugPrint("Database version %s sucessfully created", self.db.global.version)
    else
        -- detect if upgrade is neccessary or downgrade was done
        self:DebugPrint("Detected database version:", dbVersion)

        local dbMajor, dbMinor, dbPatch = parseVersion(dbVersion)
        local downGrade = false
        if (dbMajor > gMajor) then
            downGrade = true
        elseif dbMajor == gMajor then
            if (dbMinor > gMinor) then
                downGrade = true
            elseif dbMinor == gMinor then
                if (dbPatch > gPatch) then
                    downGrade = true
                end
            end
        end

        if downGrade then
            self:PrefixedPrint(cRed(self.L.Downgrade_Detected), self.L.AddonName)
        else
            local upgrade = 0
            local error = false

            if (dbMajor == 0) then
                if (dbMinor < 6) then
                    upgrade = upgrade + 1
                    dbMajor, dbMinor, dbPatch = self:Upgrade_To_v060(dbVersion)
                end
                if (dbMinor < 7) then
                    upgrade = upgrade + 1
                    dbMajor, dbMinor, dbPatch = self:Upgrade_To_v070(dbVersion)
                end
                if (dbMinor == 7) then
                    if (dbPatch < 2) then
                        upgrade = upgrade + 1
                        dbMajor, dbMinor, dbPatch = self:Upgrade_To_v072(dbVersion)
                    end
                end
                if (dbMinor < 8) then
                    upgrade = upgrade + 1
                    dbMajor, dbMinor, dbPatch = self:Upgrade_To_v080(dbVersion)
                end
                if (dbMinor < 9) then
                    upgrade = upgrade + 1
                    dbMajor, dbMinor, dbPatch = self:Upgrade_To_v090(dbVersion)
                end
            end

            if (upgrade == 0) or (error == false) then
                -- bump version number even if no update is required
                self.db.global.version = self:Format("%d.%d.%d", gMajor, gMinor, gPatch)
            end

            if (upgrade == 0) then
                self:DebugPrint("Database was up-to-date")
            elseif (error == false) then
                self:PrefixedPrint(cGreen(self.L.Upgrade_Successful))
            else
                self:PrefixedPrint(cRed(self.L.Upgrade_Error))
            end
        end
    end
end