local config = {}
local tag = "config"
local _configHash = {}
local _langHash = {}
local _lang
local base = {}

function base.__index(table, key)
  local keyIndex = rawget(table, key)
  if not keyIndex then
    warnf(tag, " Can't find " .. tostring(key) .. " from " .. rawget(table, "name"))
    return nil
  end
  return keyIndex
end

function base.__newindex(table)
  warnf(tag, "Can't insert value in " .. rawget(table, "name"))
end

base.__metatable = false

function config:_loadConfig(tname)
  local ret = _configHash[tname]
  if ret then
    return ret
  end
  local success, result = pcall(require, tname)
  if success then
    ret = result
    if ret == nil then
      errorf("return value of this lua is nil: " .. tname)
      return nil
    end
    rawset(ret, "name", tname)
    _configHash[tname] = ret
    return ret
  else
    errorf(tostring(result))
    return nil
  end
end

function config:getConfig(tname, id, key, isLang)
  if id == nil then
    return self:_loadConfig(tname)
  end
  local c = self:_loadConfig(tname)
  if c == nil then
    return nil
  end
  local val
  if key == nil then
    val = c[id]
  else
    local item = c[id]
    if item == nil then
      warnf(tag, "No this id:  " .. tname .. "[" .. id .. "]")
      val = nil
    else
      val = item[key]
    end
  end
  if val ~= nil and isLang and self.localizationProvider then
    val = self.localizationProvider(val)
  end
  return val
end

function config:unloadConfig(tname)
  _configHash[tname] = nil
  unrequire(_folder .. tname)
end

function config:setLocalizationProvider(provider)
  assert(type(provider) == "function", "provider should be a function")
  self.localizationProvider = provider
end

function config:provider(val, paras)
  return self.localizationProvider(val, paras)
end

function config:providerLua(val, paras)
  local paramList = {}
  if type(paras) == "table" then
    local index = 0
    for _, value in ipairs(paras) do
      paramList[index] = value
      index = index + 1
    end
  else
    paramList[0] = paras
  end
  local str = self:provider(val, paramList)
  return str
end

function config:getPathByHash(path)
  return path
end

function config:getPath(tname, id, key, index)
  local hash = self:getConfig(tname, id, key)
  if hash == nil then
    return nil
  end
  if index ~= nil then
    hash = hash[index]
  end
  return self:getPathByHash(hash)
end

function config:unloadAllConfigs()
  for k, v in pairs(_configHash) do
    unrequire(_folder .. k)
  end
  _configHash = {}
end

return config
