local textFiles = {}


local text = {}

textFiles.funcs = {}


local function getText(tbl,key)
    local value = rawget(tbl,key)
    if value ~= nil then
        return value
    end
    
    return rawget(tbl,tostring(key))
end

local function setMetaTables(tbl)
    setmetatable(tbl,{__index = getText})

    for k,v in pairs(tbl) do
        if type(v) == "table" then
            setMetaTables(v)
        end
    end
end


local function mergeTable(baseTable,newTable)
    for key,value in pairs(newTable) do
        if type(baseTable[key]) == "table" and type(value) == "table" then
            mergeTable(baseTable[key],value)
        else
            baseTable[key] = value
        end
    end
end

function textFiles.funcs.load(filename)
    local newText

    -- For each possible path, try to read the text file there
    for _,path in ipairs{
        Misc.episodePath().. filename,
        Misc.levelPath().. filename,
    } do
        local contents = io.readFile(path)

        if contents ~= nil then
            -- There's a text file here, so decode it
            local decodedText = json.decode(contents)

            if decodedText.funcs ~= nil then
                error("The name 'funcs' is reserved in text files",2)
            end

            if newText == nil then
                newText = decodedText
            else
                mergeTable(newText,decodedText)
            end
        end
    end

    -- If no text file was found, error
    if newText == nil then
        error("Text file '".. filename.. "' does not exist",2)
    end

    -- Set text table
    setMetaTables(newText)
    text = newText
end

function textFiles.funcs.replace(text,replaceValues)
    -- Like string.format, except the things you replace are given names.
    -- This means you can put them in any order, which is useful when dealing with multiple languages.
    local newText = ""
    local i = 1

    while (true) do
        local nextBracket,_ = text:find("{",i,true)
        if nextBracket == nil then
            newText = newText.. text:sub(i)
            break
        end

        newText = newText.. text:sub(i,nextBracket - 1)

        local closingBracket,_ = text:find("}",i,true)
        if closingBracket == nil then
            error("Unclosed bracket in text: ".. text,2)
        end

        local key = text:sub(nextBracket + 1,closingBracket - 1)

        if key[1] ~= nil and replaceValues[key] ~= nil then
            newText = newText.. tostring(replaceValues[key])
        else -- something's wrong, I can feel it
            newText = newText.. text:sub(nextBracket,closingBracket)
        end

        i = closingBracket + 1
    end

    return newText
end


setmetatable(textFiles,{
    __index = function(tbl,key)
        return getText(text,key)
    end,
})


return textFiles