local classlib = require("core.class")
local tablex = require("core.tablex")
local colors = require("ui.colors")
local consts = require("ui.consts")
local fsm = require("ui.fsm")
local lamsIDs = require("ui.lamsConsts")
local list = require("ui.list")
local menu = require("ui.menu")
local saveUtil = require("ui.saveUtil")
local slider = require("ui.slider")
local toggle = require("ui.toggle")
local util = require("ui.util")
local Audio = game.Audio
local UI = game.UI
local CalibrationScreen = classlib.Class("CalibrationScreen", fsm.UIState)
local CalibrationOff = CalibrationScreen:StateClass("CalibrationOff", fsm.UIState)
local CalibrationOn = CalibrationScreen:StateClass("CalibrationOn", fsm.UIState)
local WaitForStreamed = CalibrationScreen:StateClass("WaitForStreamed", fsm.UIState)
local HDRCalibration = CalibrationScreen:StateClass("HDRCalibration", fsm.UIState)
local SDRCalibration = CalibrationScreen:StateClass("SDRCalibration", fsm.UIState)
local calibrationScreen = CalibrationScreen.New("calibrationScreen", {
  CalibrationOff,
  CalibrationOn,
  {
    WaitForStreamed,
    HDRCalibration,
    SDRCalibration
  }
})
function CalibrationScreen:Enter()
  self.from_shell = false
  self.during_boot = false
  self:Goto("CalibrationOff")
end
function CalibrationOff:Setup()
  self.CalibrationScreen = self:GetState("calibrationScreen")
end
function CalibrationOff:Enter()
  self.CalibrationScreen.during_boot = false
  self.CalibrationScreen.from_shell = false
end
function CalibrationOff:EVT_OPEN_CALIBRATION_FROM_BOOT()
  self.CalibrationScreen.during_boot = true
  self:Goto("CalibrationOn")
end
function CalibrationOff:EVT_OPEN_CALIBRATION_SETTINGS(in_shell)
  self.CalibrationScreen.from_shell = in_shell
  self.CalibrationScreen.during_boot = false
  self:Goto("CalibrationOn")
end
function CalibrationOn:Setup()
  self.handling_event = true
  self.CalibrationScreen = self:GetState("calibrationScreen")
  self.HDRCalibrationState = self:GetState("HDRCalibration")
  self.SDRCalibrationState = self:GetState("SDRCalibration")
  self.goCalibrationScreens = util.GetUiObjByName("CalibrationScreens")
  self.thButtonPrompts = util.GetTextHandle(self.goCalibrationScreens, "ButtonPrompts")
  UI.SetText(self.thButtonPrompts, "")
  UI.SetTextIsClickable(self.thButtonPrompts)
  self.thCanChangeAnytime = util.GetTextHandle(self.goCalibrationScreens, "CanChangeAnytime")
  UI.SetText(self.thCanChangeAnytime, "")
end
function CalibrationOn:Enter()
  self.handling_event = true
  self:SetAllHandlersFalse()
  if self.CalibrationScreen.during_boot then
    UI.SendEvent("*", consts.EVT_OPENED_CALIBRATION_SCREEN)
  end
  UI.SetText(self.thCanChangeAnytime, "")
  UI.PushCamera("HUDCombatCam")
  self:WantPadEvents(true)
  self.goCalibrationScreens:Show()
  self:Goto("WaitForStreamed")
end
function CalibrationOn:SetFooterButtonPrompts()
  local footer = "[TriangleButton] " .. util.GetLAMSMsg(lamsIDs.Default) .. consts.Footer_Spacer
  if self.CalibrationScreen.during_boot then
    footer = footer .. "[AdvanceButton] " .. util.GetLAMSMsg(lamsIDs.Confirm)
  else
    footer = footer .. "[BackButton] " .. util.GetLAMSMsg(lamsIDs.Back)
  end
  UI.SetText(self.thButtonPrompts, footer)
end
function CalibrationOn:Exit()
  UI.SavePrefs()
  UI.SoftSavePlayerState()
  self:WantPadEvents(false)
  self.goCalibrationScreens:Hide()
  UI.PopCamera("HUDCombatCam")
end
function CalibrationOn:currentlyUsingHDR()
  if not game.IsHDRAvailable() then
    return false
  end
  return game.GetEnableHDR()
end
function CalibrationOn:SetDefaultValues(settingsList, menu, endFunction)
  self:SendEventUI("EVT_SHOW_SETTINGS_DIALOG_MESSAGE", {
    Header = util.GetLAMSMsg(lamsIDs.ResetToDefault),
    Body = util.GetLAMSMsg(lamsIDs.AreYouSure_SettingsReset),
    ActiveMenus = {menu},
    ActiveLists = {settingsList},
    Events = {
      Advance = {
        Text = util.GetLAMSMsg(lamsIDs.Confirm),
        Handler = function()
          endFunction()
          settingsList:SetDefaultButtonValues()
        end
      },
      Back = {
        Text = util.GetLAMSMsg(lamsIDs.Back),
        Handler = function()
          endFunction()
        end
      }
    }
  }, false)
end
function CalibrationOn:UpdateChangeAnyTimeText()
  local changeAnyTimeText = self.CalibrationScreen.during_boot and util.GetLAMSMsg(lamsIDs.CanChangeAnytime) or ""
  UI.SetText(self.thCanChangeAnytime, changeAnyTimeText)
end
function CalibrationOn:AdvanceHandler()
  local EVT_FINISH_CALIBRATION_BOOT = 902
  Audio.PlaySound("SND_UX_Menu_Tick_Confirm")
  UI.SendEvent("*", EVT_FINISH_CALIBRATION_BOOT)
  self:Goto("CalibrationOff")
end
function CalibrationOn:BackHandler()
  self:SendEventToUIFsm("settingsMenu", "EVT_CLOSE_CALIBRATION_SCREEN")
  Audio.PlaySound("SND_UX_Menu_Tick_Back")
  self:Goto("CalibrationOff")
end
function CalibrationOn:OptionsHandler()
  self:SendEventToUIFsm("settingsMenu", "EVT_CLOSE_CALIBRATION_AND_LEAVE_PAUSE")
  self:Goto("CalibrationOff")
end
function CalibrationOn:DefaultHandler()
  if self.HDRCalibrationState.instate then
    self.HDRCalibrationState:CheckForDefaults()
  elseif self.SDRCalibrationState.instate then
    self.SDRCalibrationState:CheckForDefaults()
  end
end
function CalibrationOn:EVT_Advance_Release()
  if not self.handling_event and self.CalibrationScreen.during_boot then
    self.advance = true
  end
end
function CalibrationOn:EVT_Back_Release()
  if not self.handling_event and not self.CalibrationScreen.during_boot then
    self.back = true
  end
end
function CalibrationOn:EVT_Options_Release()
  if not self.handling_event and not self.CalibrationScreen.during_boot and not self.CalibrationScreen.from_shell then
    self.back_options = true
  end
end
function CalibrationOn:EVT_Triangle_Release()
  if not self.handling_event and (self.HDRCalibrationState.instate or self.SDRCalibrationState.instate) then
    self.default = true
  end
end
function CalibrationOn:SetAllHandlersFalse()
  self.back = false
  self.back_options = false
  self.advance = false
  self.default = false
end
function CalibrationOn:Update()
  if not self.handling_event then
    if self.back then
      self.handling_event = true
      self:SetAllHandlersFalse()
      self:BackHandler()
    elseif self.back_options then
      self.handling_event = true
      self:SetAllHandlersFalse()
      self:OptionsHandler()
    elseif self.advance then
      self.handling_event = true
      self:SetAllHandlersFalse()
      self:AdvanceHandler()
    elseif self.default then
      self.handling_event = true
      self:SetAllHandlersFalse()
      self:DefaultHandler()
    end
  end
end
function WaitForStreamed:Setup()
  self.calibrationOn = self:GetState("CalibrationOn")
  self.goHDR_Calibrate = util.GetUiObjByName("HDR_Calibrate")
  self.goSDR_Calibrate = util.GetUiObjByName("SDR_Calibrate")
  self.imagesStreamedIn = false
  self.highmips_requested = false
end
function WaitForStreamed:Enter()
end
function WaitForStreamed:Exit()
  self.imagesStreamedIn = false
  self.highmips_requested = false
end
function WaitForStreamed:Update()
  if not self.imagesStreamedIn then
    self.goHDR_Calibrate:RequestLoadHighMips(true)
    self.goSDR_Calibrate:RequestLoadHighMips(true)
    if not self.highmips_requested then
      self.highmips_requested = true
    elseif self.goHDR_Calibrate:CheckMaterialFullyStreamed() and self.goSDR_Calibrate:CheckMaterialFullyStreamed() then
      self.imagesStreamedIn = true
      self:FinishedStreamed()
    end
  end
end
function WaitForStreamed:FinishedStreamed()
  if self.calibrationOn:currentlyUsingHDR() then
    self:Goto("HDRCalibration")
  else
    self:Goto("SDRCalibration")
  end
end
function HDRCalibration:Setup()
  self.instate = false
  self.calibrationOn = self:GetState("CalibrationOn")
  self.toolTip = util.GetUiObjByName("CalibrationToolTip")
  self.th_tooltip = util.GetTextHandle(self.toolTip)
  self.menu = menu.Menu.New(self, {})
  local calibrationList = list.List.New(self, {
    MaxFocusableObjectCount = 3,
    ListObjectName = "CalibrationList",
    EmptyTextLamsID = lamsIDs.NoSettingsAvailable,
    BackingAnimFrameCount = 60,
    HoverToSelect = true,
    Button_OnGainFocus = function(button)
      self:SetToopTip(button)
    end
  })
  self.menu:SetList("HDRSettings", calibrationList)
  self.settingsOn = self:GetState("SettingsOn")
  self.enableHDRtoggle = toggle.Toggle.New(self, {
    Name = "enableHDR",
    Get = function()
      return game.GetEnableHDR()
    end,
    Set = function(value)
      game.SetEnableHDR(value)
      self:WhatMenuToGoTo()
    end
  })
  self.HDRBrightnessSlider = slider.Slider.New(self, {
    Name = "brightnessHDR",
    TextFormat = "%d",
    Get = function()
      return game.GetHDRSlope()
    end,
    Set = function(value)
      game.SetHDRSlope(value)
    end,
    MinValue = 0,
    MaxValue = 100,
    Delta = 1,
    Default = function()
      return 50
    end
  })
  self.HDRContrastSlider = slider.Slider.New(self, {
    Name = "contrastHDR",
    TextFormat = "%d",
    Get = function()
      return game.GetHDRContrast()
    end,
    Set = function(value)
      game.SetHDRContrast(value)
    end,
    MinValue = 0,
    MaxValue = 100,
    Delta = 1,
    Default = function()
      return 50
    end
  })
  self.calibrationInfo = {
    {
      Item = "enableHDRtoggle",
      Text = util.GetLAMSMsg(lamsIDs.EnableHDR),
      ActivationList = {
        {
          Item = self.enableHDRtoggle
        }
      }
    },
    {
      Item = "brightnessHDR",
      Text = util.GetLAMSMsg(lamsIDs.Brightness),
      ActivationList = {
        {
          Item = self.HDRBrightnessSlider
        }
      },
      ToolTip = util.GetLAMSMsg(lamsIDs.HDRBrightnessDesc)
    },
    {
      Item = "contrastHDR",
      Text = util.GetLAMSMsg(lamsIDs.Contrast),
      ActivationList = {
        {
          Item = self.HDRContrastSlider
        }
      },
      ToolTip = util.GetLAMSMsg(lamsIDs.HDRContrastDesc)
    }
  }
end
function HDRCalibration:Enter()
  self.instate = true
  self.calibrationOn.handling_event = false
  self.menu:Activate()
  util.Show("CalibrationToolTip")
  self.calibrationOn:UpdateChangeAnyTimeText()
  self:RefreshCalibrationList()
  util.Show("HDR_Calibrate")
  self.calibrationOn:SetFooterButtonPrompts()
end
function HDRCalibration:Exit()
  self.instate = false
  self.menu:Deactivate(true)
  util.Hide("HDR_Calibrate")
end
function HDRCalibration:CheckForDefaults()
  local HDRSettingsList = self.menu:GetList("HDRSettings")
  Audio.PlaySound("SND_UX_Menu_Tick_Confirm")
  self.calibrationOn:SetDefaultValues(HDRSettingsList, self.menu, function()
    self:Enter()
  end)
end
function HDRCalibration:SetToopTip(button)
  local tooltip = button._buttonToolTip
  if tooltip == nil then
    tooltip = ""
  end
  UI.SetText(self.th_tooltip, tooltip)
end
function HDRCalibration:WhatMenuToGoTo()
  if self.calibrationOn:currentlyUsingHDR() then
    self:RefreshCalibrationList()
  else
    self:Goto("SDRCalibration")
  end
end
function HDRCalibration:RefreshCalibrationList()
  local calibrationList = self.menu:GetList("HDRSettings")
  if calibrationList ~= nil then
    local newItemArray = self.calibrationInfo
    local showList = false
    local useOnGainFocus = false
    local itemDetermineFocusabilityFunc = function(settingsInfo)
      return settingsInfo.ButtonType ~= "category"
    end
    local itemGetTextFunc = function(settingsInfo)
      return settingsInfo.Text
    end
    calibrationList:Refresh(newItemArray, showList, useOnGainFocus, itemDetermineFocusabilityFunc, itemGetTextFunc)
    local activate_showList = true
    local activate_useOnGainFocus = true
    calibrationList:Activate(activate_showList, activate_useOnGainFocus)
  end
end
function HDRCalibration:Update()
  if game.IsHDRAvailable == nil or not game.IsHDRAvailable() then
    game.SetEnableHDR(false)
    self:WhatMenuToGoTo()
  end
end
function SDRCalibration:Setup()
  self.instate = false
  self.calibrationOn = self:GetState("CalibrationOn")
  self.toolTip = util.GetUiObjByName("CalibrationToolTip")
  self.th_tooltip = util.GetTextHandle(self.toolTip)
  self.isHDRAvailable = false
  self.menu = menu.Menu.New(self, {})
  local calibrationList = list.List.New(self, {
    MaxFocusableObjectCount = 3,
    ListObjectName = "CalibrationList",
    EmptyTextLamsID = lamsIDs.NoSettingsAvailable,
    BackingAnimFrameCount = 60,
    HoverToSelect = true,
    Button_OnGainFocus = function(button)
      self:SetToopTip(button)
    end
  })
  self.menu:SetList("SDRSettings", calibrationList)
  self.settingsOn = self:GetState("SettingsOn")
  self.enableHDRtoggle = toggle.Toggle.New(self, {
    Name = "enableHDR",
    Get = function()
      return game.GetEnableHDR()
    end,
    Set = function(value)
      game.SetEnableHDR(value)
      self:WhatMenuToGoTo()
    end,
    Settings = self:GetHDREnableToggleList()
  })
  self.brightnessSlider = slider.Slider.New(self, {
    Name = "brightnessSlider",
    TextFormat = "%d",
    Get = function()
      return game.GetBrightness()
    end,
    Set = function(value)
      game.SetBrightness(value)
    end,
    MinValue = 0,
    MaxValue = 100,
    Delta = 1,
    Default = function()
      return 50
    end
  })
  local HDRTip
  if game.IsHDRAvailable ~= nil and not game.IsHDRAvailable() then
    if game.CanRender4K == nil then
      HDRTip = util.GetLAMSMsg(lamsIDs.HDRNotAvailablePC)
    else
      HDRTip = util.GetLAMSMsg(lamsIDs.HDRNotAvailable)
    end
  end
  self.calibrationInfo = {
    {
      Item = "enableHDRtoggle",
      Text = util.GetLAMSMsg(lamsIDs.EnableHDR),
      ActivationList = {
        {
          Item = self.enableHDRtoggle
        }
      },
      ToolTip = HDRTip
    },
    {
      Item = "brightnessSlider",
      Text = util.GetLAMSMsg(lamsIDs.Brightness),
      ActivationList = {
        {
          Item = self.brightnessSlider
        }
      },
      ToolTip = util.GetLAMSMsg(lamsIDs.SDRBrightnessDesc)
    }
  }
end
function SDRCalibration:WhatMenuToGoTo()
  if not self:IsActive() then
    return
  end
  if self.calibrationOn:currentlyUsingHDR() then
    self:Goto("HDRCalibration")
  else
    self:RefreshCalibrationList()
  end
end
function SDRCalibration:Enter()
  self.instate = true
  self.calibrationOn.handling_event = false
  self.isHDRAvailable = false
  if game.IsHDRAvailable ~= nil and game.IsHDRAvailable() then
    self.isHDRAvailable = true
  end
  self.menu:Activate()
  util.Show("SDR_Calibrate")
  util.Show("CalibrationToolTip")
  self.calibrationOn:UpdateChangeAnyTimeText()
  self.calibrationOn:SetFooterButtonPrompts()
  local HDRTip
  if game.IsHDRAvailable ~= nil and not game.IsHDRAvailable() then
    if game.CanRender4K == nil then
      HDRTip = util.GetLAMSMsg(lamsIDs.HDRNotAvailablePC)
    else
      HDRTip = util.GetLAMSMsg(lamsIDs.HDRNotAvailable)
    end
  end
  self.calibrationInfo[1].ToolTip = HDRTip
  self:RefreshCalibrationList()
  local calibrationList = self.menu:GetList("SDRSettings")
  if game.IsHDRAvailable ~= nil and not game.IsHDRAvailable() then
    self:CheckDisabledButton(calibrationList, 1, true)
    self:CheckDisabledButton(self.enableHDRtoggle, 1, true)
  end
  self.enableHDRtoggle:OverrideSettings(self:GetHDREnableToggleList())
end
function SDRCalibration:Exit()
  self.instate = false
  local calibrationList = self.menu:GetList("SDRSettings")
  self:ClearDisableButton(calibrationList, 1)
  self:ClearDisableButton(self.enableHDRtoggle, 1)
  self.menu:Deactivate(true)
  util.Hide("SDR_Calibrate")
end
function SDRCalibration:CheckDisabledButton(setting_list, index, disabled)
  if setting_list == nil then
    return
  end
  local setting_button = setting_list:GetButton(index)
  if setting_button then
    if disabled then
      setting_button:SetTextColor(colors.Text_Settings_Disabled, "medium_text_settings1")
    else
      setting_button:SetTextColor(colors.Text_Settings1, "medium_text_settings1")
    end
  end
end
function SDRCalibration:ClearDisableButton(setting_list, index)
  if setting_list == nil then
    return
  end
  local setting_button = setting_list:GetButton(index)
  if setting_button then
    setting_button:SetTextColor(colors.Text_Settings1, "medium_text_settings1")
  end
end
function SDRCalibration:GetHDREnableToggleList()
  if game.IsHDRAvailable ~= nil and not game.IsHDRAvailable() then
    return {
      {
        Text = util.GetLAMSMsg(lamsIDs.Off),
        Value = false
      }
    }
  end
end
function SDRCalibration:CheckForDefaults()
  local SDRSettingsList = self.menu:GetList("SDRSettings")
  Audio.PlaySound("SND_UX_Menu_Tick_Confirm")
  self.calibrationOn:SetDefaultValues(SDRSettingsList, self.menu, function()
    self:Enter()
  end)
end
function SDRCalibration:SetToopTip(button)
  local tooltip = button._buttonToolTip
  if tooltip == nil then
    tooltip = ""
  end
  UI.SetText(self.th_tooltip, tooltip)
end
function SDRCalibration:RefreshCalibrationList()
  local calibrationList = self.menu:GetList("SDRSettings")
  if calibrationList ~= nil then
    local newItemArray = self.calibrationInfo
    local showList = false
    local useOnGainFocus = false
    local itemDetermineFocusabilityFunc = function(settingsInfo)
      if settingsInfo.ButtonType == "category" then
        return nil
      end
      if settingsInfo.Enabled ~= nil and not settingsInfo.Enabled() then
        return nil
      end
      return true
    end
    local itemGetTextFunc = function(settingsInfo)
      return settingsInfo.Text
    end
    calibrationList:Refresh(newItemArray, showList, useOnGainFocus, itemDetermineFocusabilityFunc, itemGetTextFunc)
    local activate_showList = true
    local activate_useOnGainFocus = true
    calibrationList:Activate(activate_showList, activate_useOnGainFocus)
  end
end
function SDRCalibration:Update()
  local isHDRAvailable = false
  if game.IsHDRAvailable ~= nil and game.IsHDRAvailable() then
    isHDRAvailable = true
  end
  if self.isHDRAvailable ~= isHDRAvailable then
    local HDRTip
    local calibrationList = self.menu:GetList("SDRSettings")
    if isHDRAvailable then
      self:ClearDisableButton(calibrationList, 1)
      self:ClearDisableButton(self.enableHDRtoggle, 1)
    else
      if game.CanRender4K == nil then
        HDRTip = util.GetLAMSMsg(lamsIDs.HDRNotAvailablePC)
      else
        HDRTip = util.GetLAMSMsg(lamsIDs.HDRNotAvailable)
      end
      self:CheckDisabledButton(calibrationList, 1, true)
      self:CheckDisabledButton(self.enableHDRtoggle, 1, true)
    end
    if HDRTip == nil then
      UI.SetText(self.th_tooltip, "")
    else
      UI.SetText(self.th_tooltip, HDRTip)
    end
    self.calibrationInfo[1].ToolTip = HDRTip
    self:RefreshCalibrationList()
    self.enableHDRtoggle:OverrideSettings(self:GetHDREnableToggleList())
    self.isHDRAvailable = isHDRAvailable
  end
end
