------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------

local love       = require 'love'
local magiclines = require 'src.utils.mgclines'


------------------------------------------------------------------------------
-- Constants
------------------------------------------------------------------------------

local SETTINGS_PATH = 'settings.ini'


------------------------------------------------------------------------------
-- Module definitions
------------------------------------------------------------------------------

local settings = {
    -- Default setting values.
    permadeath = true,
    forward    = 'w',
    backward   = 's',
    stepleft   = 'a',
    stepright  = 'd',
    turnleft   = 'q',
    turnright  = 'e',
    musicvol   = 75,
    soundvol   = 100,
}


------------------------------------------------------------------------------
-- Private module methods
------------------------------------------------------------------------------

function settings:_parse_settings_str(s)
    -- For each line in the data string.
    for line in magiclines(s) do
        -- Check if the line matches a key=value pair
        local k, v = string.match(line, '(%w+)=(.+)')

        if k and v then
            -- If the line matches then check if it has a known settings key.
            if self[k] ~= nil then
                -- If the key is valid then cast the value to it's expected data type and store it.
                -- Fail if the cast is not doable.
                if v == 'true' then
                    if type(self[k]) ~= 'boolean' then error(string.format('Invalid value for %s in settings', k)) end
                    self[k] = true
                elseif v == 'false' then
                    if type(self[k]) ~= 'boolean' then error(string.format('Invalid value for %s in settings', k)) end
                    self[k] = false
                elseif tonumber(v) then
                    if type(self[k]) ~= 'number' then error(string.format('Invalid value for %s in settings', k)) end
                    self[k] = tonumber(v)
                else
                    self[k] = v
                end
            else
                -- Fail on an unknown key.
                error(string.format('Unknown settings key "%s"', k))
            end
        end
    end
end


function settings:_get_settings_str()
    -- Start with the settings category.
    local s = '[settings]\n'

    -- For each value in the settings table.
    for k, v in pairs(self) do
        -- If the value isn't a function then it is a setting.
        if type(v) ~= 'function' then
            -- Format the value as key=value.
            s = s .. string.format('%s=%s\n', k, v)
        end
    end

    return s
end


function settings:_open_or_create()
    if not love.filesystem.exists(SETTINGS_PATH) then
        -- If the settings file doesn't exist then create it with the default values.
        local setts = self:_get_settings_str()
        love.filesystem.write(SETTINGS_PATH, setts)
        return setts
    else
        if not love.filesystem.isFile(SETTINGS_PATH) then
            -- Fail if the settings path points to a directory.
            error ("Settings path exists and isn't a file")
        else
            -- Else read the settings.
            return love.filesystem.read(SETTINGS_PATH)
        end
    end
end


------------------------------------------------------------------------------
-- Public module methods
------------------------------------------------------------------------------

function settings:load_settings()
    -- Obtain the settings data and parse it.
    local s = self:_open_or_create()
    self:_parse_settings_str(s)
end


function settings:save_settings()
    if not love.filesystem.exists(SETTINGS_PATH) or love.filesystem.isFile(SETTINGS_PATH) then
        -- If the settings file doesn't exist or it exists and is a file then save the current data.
        love.filesystem.write(SETTINGS_PATH, self:_get_settings_str())
    else
        -- Fail if the settings path points to a directory.
        error("Settings path exists and isn't a file")
    end
end


------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------

return settings
