local this = class("settingStore", G_BaseStore)
local _optionDataTpl = L_GameTpl:getOptionDataTpl()
this:importPartialClass(require(L_R.store .. "setting.settingState"))
this.saveKey = {
  setting_normal = "setting_%s_%s",
  setting_startPos = "setting_startPos_%s",
  setting_pos = "setting_pos_%s",
  setting_startPos_joystickObj = "setting_startPos_joystickObj",
  setting_pos_joystickObj = "setting_pos_joystickObj"
}
this.event = {
  refreshEquipment = "refreshEquipment",
  refreshSceneQuality = "refreshQuality",
  refreshBright = "refreshBright",
  refreshContrast = "refreshContrast",
  refreshSaturation = "refreshSaturation",
  changeKey = "changeKey",
  showStateChange = "showStateChange"
}

function this:ctor()
  self.adapter = nil
  self.checkAdapter = nil
  self:injectAdapter()
  this.super.ctor(self)
  if self.timer == nil then
    self.timer = Timer.repeated(0.015, self.update, self)
  end
end

function this:clear()
end

function this:injectAdapter()
  self.checkAdapter = require(L_R.store .. "setting.adapter.settingCheckAdapter").new()
  local equip = L_DeviceTpl:getEquipment()
  if equip == L_Const.equipment.mobile then
    self.adapter = require(L_R.store .. "setting.adapter.settingAdapter_mobile").new()
  else
    self.adapter = require(L_R.store .. "setting.adapter.settingAdapter_pc").new()
  end
end

function this:injectCache(playerId)
  if playerId ~= nil then
    self:setLastPlayerId(playerId)
  end
  playerId = playerId or tonumber(self:getLastPlayerId())
  local isChanged = self.data.recordId ~= playerId
  if isChanged then
    self.data.recordId = playerId
    local data = _optionDataTpl:getConfig()
    for _, tpl in ipairs(data) do
      local id = _optionDataTpl:getId(tpl)
      local key = self:getSettingKey(playerId, id)
      local initData = self:getPrefsString(key)
      if string.isEmpty(initData) or id == L_Const.settingType.resolution or id == L_Const.settingType.windowMode then
        initData = _optionDataTpl:getDefaultPara(tpl)
      end
      self.data.cache[id] = initData
    end
    self:initKeyJson(playerId)
    self.adapter:initText(self:getSetNumData(L_Const.settingType.text))
    self.adapter:adapt(L_Const.settingType.mute, self:getSetData(L_Const.settingType.mute))
    self.adapter:adapt(L_Const.settingType.bgm, self:getSetData(L_Const.settingType.bgm))
    self.adapter:adapt(L_Const.settingType.se, self:getSetData(L_Const.settingType.se))
    self.adapter:adapt(L_Const.settingType.cv, self:getSetData(L_Const.settingType.cv))
    self.adapter:adapt(L_Const.settingType.language, self:getSetData(L_Const.settingType.language))
    self.adapter:adapt(L_Const.settingType.renderAccuracy, self:getSetData(L_Const.settingType.renderAccuracy))
  end
  return isChanged
end

function this:injectAndApplyCache(playerId)
  self:injectCache(playerId)
  local ignore = {
    [L_Const.settingType.text] = true,
    [L_Const.settingType.mute] = true,
    [L_Const.settingType.bgm] = true,
    [L_Const.settingType.se] = true,
    [L_Const.settingType.cv] = true,
    [L_Const.settingType.windowMode] = true,
    [L_Const.settingType.resolution] = true,
    [L_Const.settingType.language] = true,
    [L_Const.settingType.renderAccuracy] = true
  }
  self:applyInit(ignore)
end

function this:applyInit(ignore)
  for id, v in pairs(self.data.cache) do
    if ignore == nil or not ignore[id] then
      self.adapter:adapt(id, v)
    end
  end
end

function this:setSetting(id, value)
  self.data.cache[id] = tostring(value)
  local playerId = L_PlayerStore:getPlayerId() or 0
  local key = self:getSettingKey(playerId, id)
  self:setPrefsString(key, tostring(value))
  self.adapter:adapt(id, value)
  if id == L_Const.settingType.module or id == L_Const.settingType.shadow then
    self:call(this.event.refreshSceneQuality)
  elseif L_Const.settingKey[id] then
    self.data.keyDirty = true
    self:call(this.event.changeKey, id)
  elseif id == L_Const.settingType.bright then
    self:setbright(value)
    self:call(this.event.refreshBright, id, value)
  elseif id == L_Const.settingType.contrast then
    self:setContrast(value)
    self:call(this.event.refreshContrast, id, value)
  elseif id == L_Const.settingType.saturation then
    self:setSaturation(value)
    self:call(this.event.refreshSaturation, id, value)
  end
end

function this:calResolutionFactor()
  return self.adapter:calResolutionFactor()
end

function this:refreshVolatileSetting()
  local data = _optionDataTpl:getConfig()
  for _, tpl in ipairs(data) do
    local id = _optionDataTpl:getId(tpl)
    if id == L_Const.settingType.resolution or id == L_Const.settingType.windowMode then
      self.data.cache[id] = _optionDataTpl:getDefaultPara(tpl)
    end
  end
end

function this:initKeyJson(playerId)
  playerId = playerId or L_PlayerStore:getPlayerId() or 0
  local key = string.format("settingkey_%s", playerId)
  local json = self:getPrefsString(key)
  C_InputManager.ReadJson(json)
end

function this:trySaveKeyJson()
  if not self:getKeyDirty() then
    return
  end
  self.data.keyDirty = false
  local id = L_PlayerStore:getPlayerId() or 0
  local key = string.format("settingkey_%s", id)
  local json = C_InputManager.SaveAsJson()
  self:setPrefsString(key, json)
end

function this:setMoveBlockControlConfig(joyStickRectPos, childControlPosList)
  for i, v in pairs(childControlPosList) do
    self:setPrefsString(self:getKeyWithPlayerId(string.format(self.saveKey.setting_pos, i)), string.concat(v.x, "_", v.y))
  end
  local str = string.concat(joyStickRectPos.x, "_", joyStickRectPos.y)
  self:setPrefsString(self:getKeyWithPlayerId(self.saveKey.setting_pos_joystickObj), str)
end

function this:setStartMoveBlockControlConfig(joyStickRectPos, childControlPosList)
  for i, v in ipairs(childControlPosList) do
    self:setPrefsString(self:getKeyWithPlayerId(string.format(self.saveKey.setting_startPos, i)), string.concat(v.x, "_", v.y))
  end
  self:setPrefsString(self:getKeyWithPlayerId(self.saveKey.setting_startPos_joystickObj), string.concat(joyStickRectPos.x, "_", joyStickRectPos.y))
end

function this:setSoftCamera()
  if L_CameraManager:getCurCamController():getMode() == L_Const.cameraMode.world then
    L_CameraManager:getCurCamController():refreshSoftCamera()
  end
end

function this:setLoginSave(selectedServerId, selectedServerName)
  if selectedServerId then
    self:setPrefsInt(L_Const.prefsKey.serverId, selectedServerId)
  end
  if selectedServerName then
    self:setPrefsString(L_Const.prefsKey.serverName, selectedServerName)
  end
end

function this:removeAllOption()
  local curId = self:getLastPlayerId()
  local lastId = self:getPrefsString(L_Const.prefsKey.lastPlayerId)
  for i, v in pairs(self.data.cache) do
    local key = self:getSettingKey(curId, i)
    self:deleteKey(key)
    if lastId and curId ~= lastId then
      local key1 = self:getSettingKey(lastId, i)
      self:deleteKey(key1)
    end
  end
end

function this:setClearCache()
  self:removeAllOption()
  self:deleteKey(L_Const.prefsKey.firstSetTemp)
  self:deleteKey(L_Const.prefsKey.playerAccount)
  self:deleteKey(L_Const.prefsKey.serverId)
  self:deleteKey(L_Const.prefsKey.serverName)
  self:deleteKey(L_Const.prefsKey.curTraceTask)
  self:deleteKey(L_Const.prefsKey.lastPlayerId)
end

function this:setCurTraceTask(number)
  self:setPrefsInt(L_Const.prefsKey.curTraceTask, number)
end

function this:setPrefsString(str, val)
  C_PlayerPrefsUtility.SetString(str, val)
end

function this:setPrefsInt(str, int)
  C_PlayerPrefsUtility.SetInt(str, int)
end

function this:setPrefsBool(str, bool)
  C_PlayerPrefsUtility.SetBool(str, bool)
end

function this:deleteKey(key)
  C_PlayerPrefsUtility.DeleteKey(key)
end

function this:_deleteAll()
  C_PlayerPrefsUtility.DeleteAll()
end

function this:getIsExistsLangPack(value)
  return true
end

function this:getIsExistsLangPackByTag(tag)
  return C_PlayerPrefsUtility.GetBool(tag)
end

function this:getLangPackSize(value)
  return 0
end

function this:getLangPackSizeByTag(tag)
  return 0
end

function this:downLangPack(value)
end

function this:setCurrentPack(value)
end

function this:getCurrentLangPackDownSize()
  return 0
end

function this:getIsLangPackDownComplete()
  return true
end

function this:getCurrentLangPackSize()
  return 0
end

local languageText = ""

function this:setSelectLangText(lang)
  languageText = lang
end

function this:getSelectLangText()
  return languageText
end

function this:byteToGBText(size)
  if size == nil or size == 0 then
    return "0"
  end
  local gb = size / 1073741824
  if 0.01 <= gb then
    return string.format("%.2f GB", gb)
  else
    local kb = size / 1024
    return string.format("%.2f KB", kb)
  end
end

function this:deleteLangPack(lang)
  return true
end

function this:setbright(value)
  local res = tonumber(value)
  if res <= 50 then
    res = 0.012 * res + 0.4
  else
    res = 0.036 * res - 0.8
  end
  C_GlobalEffectMgr.SetBSCBright(res)
end

function this:setSaturation(value)
  local res = tonumber(value)
  if res <= 50 then
    res = 0.12 * res - 6
  else
    res = 0.08 * res - 4
  end
  C_GlobalEffectMgr.SetBSCSaturation(res)
end

function this:setContrast(value)
  local res = tonumber(value)
  res = 0.04 * res - 2
  C_GlobalEffectMgr.SetBSCContrast(res)
end

function this:recordChanged(settingType)
  self.changedRecord = self.changedRecord or {}
  self.changedRecord[settingType] = 1
end

function this:reportSetting()
  local logList = {}
  if self.changedRecord[L_Const.settingType.softCamera] or self.changedRecord[L_Const.settingType.cameraSpeed] then
    local log = {
      sensitivity = tonumber(self:getSetData(L_Const.settingType.cameraSpeed)),
      soft = tonumber(self:getSetData(L_Const.settingType.softCamera))
    }
    logList[L_Const.logEventName.camera_setup] = log
  end
  for i, v in pairs(logList) do
    L_GameUtil.logEvent(i, v)
  end
  self.changedRecord = {}
end

function this:update()
  local width = C_Screen.width
  if self.preWidth ~= width then
    self.preWidth = width
    print("\229\136\134\232\190\168\231\142\135\229\143\152\229\140\150" .. tostring(width))
    self:onResolutionChange()
  end
end

function this:onResolutionChange()
  local is1080 = L_GameUtil.isUnder1080()
  local isDlssOn = L_SettingStore:getSetData(L_Const.settingType.dlss) == tostring(true) and L_SettingStore.checkAdapter:checkState(L_Const.settingType.dlss) == L_Const.settingState.none
  if not is1080 and isDlssOn then
    local level = L_SettingStore:getSetData(L_Const.settingType.dlssLevel)
    local levelStr = L_Const.dlssLevel[tostring(level)]
    C_DeviceGradingManager.SetQualityValue("PipelineRenderScale", levelStr)
  else
    local rs = L_SettingStore:getSetData(L_Const.settingType.renderAccuracy)
    self.adapter:adapt(L_Const.settingType.renderAccuracy, rs)
  end
  if L_GameUtil.isUnder1080() then
    L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.dlss, L_Const.settingState.hide)
    L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.dlssLevel, L_Const.settingState.hide)
    L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.renderAccuracy, L_Const.settingState.none)
  else
    L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.dlss, L_Const.settingState.none)
    local dlssOn = L_SettingStore:getSetData(L_Const.settingType.dlss) == "true"
    local dlssSupport = C_SettingUtility.IsSupportDLSS()
    if dlssOn and dlssSupport then
      L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.dlssLevel, L_Const.settingState.none)
      L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.renderAccuracy, L_Const.settingState.block)
    else
      L_SettingStore:call(L_SettingStore.event.showStateChange, L_Const.settingType.renderAccuracy, L_Const.settingState.none)
    end
  end
end

return this
