local GlobalConst = require "app/config/localization/localization_global_const"
local FontMgr = require "app/common/font_manager"

local I18N = {
	configs = {},
	cacheGlobalFormatParamSequnce = {},
	cacheNormalFormatParamSequnce = {},
    cacheGlobalIndex = 0,
}

I18N.GlobalConst = GlobalConst

local MONSTER_METATABLE = {
	__index = function(t, k)
		if rawget(t, k) == nil then
			local realId = ConfigManager:getConfig("monster")[k].monster_baseid
			local v = t._realConfig[realId]
			if v then
				rawset(t, k, v)
			end
			return v
		end
		return rawget(t, k)
	end
}

local CONFIG_PATH = "app/config/strings/%s/"

local SUPPORT_LANGUAGE_LIST = {
	GConst.LANGUAGE.ENGLISH,
	GConst.LANGUAGE.JAPANESE, -- 日本
	GConst.LANGUAGE.KOREAN, -- 韩国
	GConst.LANGUAGE.CHINESE_TC,
	GConst.LANGUAGE.CHINESE,
	-- GConst.LANGUAGE.RUSSIAN, -- 俄罗斯
	GConst.LANGUAGE.PORTUGUESE, -- 葡萄牙
	GConst.LANGUAGE.VIETNAMESE, -- 越南
	GConst.LANGUAGE.INDONESIA, -- 印度尼西亚
	GConst.LANGUAGE.THAILAND, -- 泰国
	-- GConst.LANGUAGE.FRENCH, -- 法语
	-- GConst.LANGUAGE.ITALIAN, -- 意大利
	-- GConst.LANGUAGE.GERMAN, -- 德国
	GConst.LANGUAGE.SPANISH, -- 西班牙
	-- GConst.LANGUAGE.TURKISH, -- 土耳其
	-- GConst.LANGUAGE.MALAYSIA, -- 马来西亚
}

local SUPPORT_SERVER_LANGUAGE = {
	[GConst.LANGUAGE.ENGLISH] = "en_US",
	[GConst.LANGUAGE.CHINESE] = "zh_CN",
	[GConst.LANGUAGE.CHINESE_TC] = "zh_TW",
	[GConst.LANGUAGE.FRENCH] = "fr_FR",
	[GConst.LANGUAGE.GERMAN] = "de_DE",
	[GConst.LANGUAGE.RUSSIAN] = "ru_RU",
	[GConst.LANGUAGE.THAILAND] = "th_TH",
	[GConst.LANGUAGE.INDONESIA] = "in_ID",
	[GConst.LANGUAGE.VIETNAMESE] = "vi_VN",
	[GConst.LANGUAGE.JAPANESE] = "ja_JP",
	[GConst.LANGUAGE.KOREAN] = "ko_KR",
	[GConst.LANGUAGE.SPANISH] = "es_ES",
	[GConst.LANGUAGE.PORTUGUESE] = "pt_BR",
}

local MOBILE_LANG_MAP = {
	["en"] = GConst.LANGUAGE.ENGLISH,
	["cn"] = GConst.LANGUAGE.CHINESE,
	["zh"] = GConst.LANGUAGE.CHINESE_TC,
	["fr"] = GConst.LANGUAGE.FRENCH,
	["it"] = GConst.LANGUAGE.ITALIAN,
	["de"] = GConst.LANGUAGE.GERMAN,
	["es"] = GConst.LANGUAGE.SPANISH,
	["ru"] = GConst.LANGUAGE.RUSSIAN,
	["pt"] = GConst.LANGUAGE.PORTUGUESE,
	["tr"] = GConst.LANGUAGE.TURKISH,
	["th"] = GConst.LANGUAGE.THAILAND,
	["ms"] = GConst.LANGUAGE.MALAYSIA,
	["in"] = GConst.LANGUAGE.INDONESIA,
	["vi"] = GConst.LANGUAGE.VIETNAMESE,
	["ja"] = GConst.LANGUAGE.JAPANESE,
	["ko"] = GConst.LANGUAGE.KOREAN,
}

local LANGUAGE_NOMARL_SPRITE = {
	[GConst.LANGUAGE.ENGLISH] = "setting_language_en1",
	[GConst.LANGUAGE.CHINESE] = "setting_language_cn1",
	[GConst.LANGUAGE.CHINESE_TC] = "setting_language_tw1",
	[GConst.LANGUAGE.FRENCH] = "setting_language_fr1",
	[GConst.LANGUAGE.ITALIAN] = "setting_language_it1",
	[GConst.LANGUAGE.GERMAN] = "setting_language_de1",
	[GConst.LANGUAGE.SPANISH] = "setting_language_sp1",
	[GConst.LANGUAGE.RUSSIAN] = "setting_language_ru1",
	[GConst.LANGUAGE.PORTUGUESE] = "setting_language_pt1",
	[GConst.LANGUAGE.TURKISH] = "setting_language_tr1",
	[GConst.LANGUAGE.THAILAND] = "setting_language_th1",
	[GConst.LANGUAGE.MALAYSIA] = "setting_language_ms1",
	[GConst.LANGUAGE.INDONESIA] = "setting_language_id1",

}

local LANGUAGE_HIGHLIGHT_SPRITE = {
	[GConst.LANGUAGE.ENGLISH] = "setting_language_en2",
	[GConst.LANGUAGE.CHINESE] = "setting_language_cn2",
	[GConst.LANGUAGE.CHINESE_TC] = "setting_language_tw2",
	[GConst.LANGUAGE.FRENCH] = "setting_language_fr2",
	[GConst.LANGUAGE.ITALIAN] = "setting_language_it2",
	[GConst.LANGUAGE.GERMAN] = "setting_language_de2",
	[GConst.LANGUAGE.SPANISH] = "setting_language_sp2",
	[GConst.LANGUAGE.RUSSIAN] = "setting_language_ru2",
	[GConst.LANGUAGE.PORTUGUESE] = "setting_language_pt2",
	[GConst.LANGUAGE.TURKISH] = "setting_language_tr2",
	[GConst.LANGUAGE.THAILAND] = "setting_language_th2",
	[GConst.LANGUAGE.MALAYSIA] = "setting_language_ms2",
	[GConst.LANGUAGE.INDONESIA] = "setting_language_id2",
}

function I18N:init()
	local curLanguage = LocalData:getSelectedLanguage()
	if curLanguage == "" or not self:supportLanguage(curLanguage) then
		curLanguage = self:getSystemLanguage()
		if curLanguage == nil then
			curLanguage = CS.BF.BFPlatform.GetCurrentLanguageInfo():GetFallbackLanguage()
		end
	end

	local changeStatus = self:setLanguage(curLanguage, true)
	if changeStatus then
		FontMgr:changeLanguage(self.curLanguage or GConst.LANGUAGE.ENGLISH)
	end
end

function I18N:supportLanguage(language)
	if self.supportLanguageMap == nil then
		self.supportLanguageMap = {}
		for k, v in ipairs(SUPPORT_LANGUAGE_LIST) do
			self.supportLanguageMap[v] = true
		end
	end
	return self.supportLanguageMap[language]
end

function I18N:setLanguage(language, firstInit)
	if not self:supportLanguage(language) then
		local fallbackLanguage = CS.BF.BFPlatform.GetCurrentLanguageInfo():GetFallbackLanguage()
		language = fallbackLanguage
	end

	if not language or language == self.curLanguage then
		return
	end
	LocalData:setSelectedLanguage(language)
	self:clear()
	self.curLanguage = language

	self.configPath = string.format(CONFIG_PATH, self.curLanguage)

	local monsterTable = {
		_realConfig = false
	}
	setmetatable(monsterTable, MONSTER_METATABLE)
	self.configs["monster"] = {
		data = monsterTable,
	}
	if not firstInit then
		self:preLoadConfig()
	end

	Logger.logHighlight("setLanguage = %s", language)
	return true
end

function I18N:onFontLoaded(callback)
	FontMgr:onFontLoaded(callback)
end

function I18N:preLoadConfig()
	-- local config = self:getConfig("monster")
	-- if not config._realConfig then
	-- 	config._realConfig = require(self.configPath .. "monster_base").data
	-- end
end

function I18N:clear()
	for name, v in pairs(self.configs) do
		self:clearConfigCache(name)
		self.configs[name] = nil
	end

	--清除缓存
	self.cacheGlobalFormatParamSequnce = {}
	self.cacheNormalFormatParamSequnce = {}
	self.cacheGlobalIndex = 0
end

function I18N:clearConfigCache(configName)
	package.loaded[self.configPath .. configName] = nil
end

function I18N:getCurLanguage()
	return self.curLanguage
end

function I18N:getLanguageSprite(language)
	return LANGUAGE_NOMARL_SPRITE[language]
end

function I18N:getSeletedSprite(language)
	return LANGUAGE_HIGHLIGHT_SPRITE[language]
end

function I18N:getSystemLanguage()
	local sdkLanguage = CS.BF.BFMain.Instance.SDKMgr:GetLanguage()
	print("I18N get sdk language " .. sdkLanguage)
	local languageInfo = string.split(sdkLanguage, "_")
	if not languageInfo or #languageInfo ~= 2 then
		print("I18N return system language nil")
		return nil
	end
	local language = languageInfo[1]
	local country = languageInfo[2]
	if language and language == "zh" then
		if country and country == "CN" then
			language = "cn"
		end
	end
	language = MOBILE_LANG_MAP[language]
	if not self:supportLanguage(language) then
		language = nil
	end
	if language then
		Logger.log("I18N return system language %s", language)
	else
		Logger.log("I18N return system language nil")
	end
	return language
end

function I18N:getSupportLanguageList()
	return SUPPORT_LANGUAGE_LIST
end

function I18N:_getConfig(configName)
	local config
	if configName == "global" then
		config = {}
		config.data = require(self.configPath .. configName)
	else
		config = require(self.configPath .. configName)
	end
	self.configs[configName] = config
	return config
end

function I18N:getConfig(configName)
	local config = self.configs[configName]
	if config == nil then
		config = self:_getConfig(configName)
	end
	return config.data
end

if NOT_PUBLISH then
	I18N.__getConfig = I18N.getConfig
	function I18N:getConfig(configName)
		if string.lower(configName) ~= configName then
			Logger.logFatal("I18N:getConfig 传入的表名不能有大写 " .. configName)
		end
		return self:__getConfig(configName)
	end
end

function I18N:getConfigWithOtherKey(configName, keyName)
	local config = self.configs[configName]
	if config == nil then
		config = self:_getConfig(configName)
	end
	if config.keys == nil then
		return nil
	end
	return config.keys[keyName]
end

function I18N:getConfigNum(configName)
	local config = self.configs[configName]
	if config == nil then
		config = self:_getConfig(configName)
	end
	return config.count
end

function I18N:getGlobalText(key, ...)
	local config = self:getConfig("global")
	local str = config[key]
	if str == nil then
		return ""
	end
	if ... then
		local param = {...}
		if self.cacheGlobalFormatParamSequnce[key] then
			self.cacheGlobalIndex = 0
			str = string.gsub(str, '{%d+}', function (s)
				self.cacheGlobalIndex = self.cacheGlobalIndex + 1
				return tostring(param[self.cacheGlobalFormatParamSequnce[key][self.cacheGlobalIndex]])
			end)
		else
			self.cacheGlobalFormatParamSequnce[key] = {}
			str = string.gsub(str, '{%d+}', function (s)
				self.cacheGlobalIndex = tonumber(string.sub(s, 2,-2)) + 1
				table.insert(self.cacheGlobalFormatParamSequnce[key], self.cacheGlobalIndex)
				return tostring(param[self.cacheGlobalIndex])
			end)
		end
	end
	return str
end

function I18N:getText(configName, index, key, ...)
	local config = self:getConfig(configName)
	local row = config[index]
	if row == nil then
		return ""
	end
	local str = row[key]
	if str == nil then
		return ""
	end
	if ... then
		local param = {...}
		key = configName .. index .. key
		if self.cacheNormalFormatParamSequnce[key] then
			self.cacheNormalIndex = 0
			str = string.gsub(str, '{%d+}', function (s)
				self.cacheNormalIndex = self.cacheNormalIndex + 1
				return tostring(param[self.cacheNormalFormatParamSequnce[key][self.cacheNormalIndex]])
			end)
		else
			self.cacheNormalFormatParamSequnce[key] = {}
			str = string.gsub(str, '{%d+}', function (s)
				self.cacheNormalIndex = tonumber(string.sub(s, 2,-2)) + 1
				table.insert(self.cacheNormalFormatParamSequnce[key], self.cacheNormalIndex)
				return tostring(param[self.cacheNormalIndex])
			end)
		end
	end

	return str
end

function I18N:getTextWithOtherKey(configName, otherKey, otherKeyValue, key, ...)
	local index = ConfigManager:getMainKeyWithOtherKey(configName, otherKey, otherKeyValue)
	return self:getText(configName, index, key, ...)
end

function I18N:getFallbackLanguage()
	if not self.fallbackLanguage then
		local languageInfo = CS.BF.BFPlatform.GetCurrentLanguageInfo()
		self.fallbackLanguage = languageInfo:GetFallbackLanguage()
	end
	return self.fallbackLanguage
end

function I18N:getLanguageAndArea()
	if SUPPORT_SERVER_LANGUAGE[self:getCurLanguage()] then
		return SUPPORT_SERVER_LANGUAGE[self:getCurLanguage()]
	end
	return SUPPORT_SERVER_LANGUAGE[GConst.LANGUAGE.ENGLISH]
end

return I18N