local lang = {}
local _configCache = {}

function lang:_loadConfig(tname)
  local ret = _configCache[tname]
  if nil ~= ret then
    return ret
  end
  ret = require(tname)
  if ret == nil then
    warnf(tag, "dont has this config: " .. tname)
    return nil
  end
  rawset(ret, "name", tname)
  _configCache[tname] = ret
  return ret
end

function lang:_unloadConfig(tname)
  _configCache[tname] = nil
  package.loaded[tname] = nil
end

function lang:_getConfig(tname, id)
  if id == nil then
    return self:_loadConfig(tname)
  else
    local c = self:_loadConfig(tname)
    if c then
      return c[id]
    end
  end
end

function lang:_translate(langString)
  if langString == nil then
    return ""
  end
  if type(langString) ~= "table" then
    return langString
  end
  local group = langString.group
  local langKey = langString.langKey
  if group == nil or langKey == nil then
    return ""
  end
  local translated = self:_getConfig(group, langKey)
  if translated == nil then
    errorf(string.format("[Lang] Failed to translate. group:%s, langKey:%s", tostring(group), tostring(langKey)))
    return "{LANG-MISSING}"
  end
  return translated
end

function lang:clear()
  for i, _ in pairs(_configCache) do
    self:_unloadConfig(i)
  end
end

function lang:get(langString, paramMap)
  local str = self:_translate(langString)
  if paramMap then
    for k, v in pairs(paramMap) do
      local findStr = "{" .. tostring(k) .. "}"
      local targetStr = string.gsub(v, "%%", "%%%%")
      str = string.gsub(str, findStr, targetStr)
    end
  end
  return str
end

function lang:fmt(str, paramMap)
  if not str or not paramMap then
    return ""
  end
  for k, v in pairs(paramMap) do
    local findStr = "{" .. tostring(k) .. "}"
    local targetStr = string.gsub(v, "%%", "%%%%")
    str = string.gsub(str, findStr, targetStr)
  end
  return str
end

return lang
