--[[
Copyright (c) 2012-2013 Kaarle Ritvanen
See LICENSE file for license details
--]]

local M = {}

local loadmods = require('acf2.loader')
local topology = require('acf2.model.root').topology
local object = require('acf2.object')
local pth = require('acf2.path')
local util = require('acf2.util')

local stringy = require('stringy')


local DataStore = object.class(
   require('acf2.transaction.backend').TransactionBackend
)

function DataStore:init()
   object.super(self, DataStore):init()
   self.backends = util.map(
      function(m) return m() end,
      loadmods('persistence/backends')
   )
end

function DataStore:split_path(path)
   local comps = pth.split(path)
   local backend = self.backends[comps[1]]
   assert(backend)
   table.remove(comps, 1)
   return backend, comps
end

function DataStore:get(path)
   local backend, comps = self:split_path(path)
   local top = topology(path)

   local res = backend:get(comps, top)

   if top then
      local t = top.type
      if t and res ~= nil then
	 local atype = type(res)

	 if t == 'table' then assert(atype == 'table')

	 else
	    assert(atype ~= 'table')

	    if t == 'string' then res = tostring(res)
	    elseif t == 'number' then res = tonumber(res)
	    elseif t == 'boolean' then
	       res = (res and res ~= 'false') and true or false
	    elseif t == 'reference' then assert(atype == 'string')
	    else assert(false) end
	 end
      end
   end

   return util.copy(res), self.mod_time[path] or 0
end

function DataStore:_set_multiple(mods)
   local bms = {}
   
   for _, mod in ipairs(mods) do
      local path, value = unpack(mod)
      local backend, comps = self:split_path(path)
      table.insert(util.setdefault(bms, backend, {}), {comps, value})
   end

   for backend, bm in pairs(bms) do backend:set(bm) end
end


return DataStore()
