--[[
			// SetAccountCredentialsScreen.lua
]]
local CoreGui = Game:GetService("CoreGui")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")

local ContextActionService = game:GetService('ContextActionService')
local GuiService = game:GetService('GuiService')

local AccountManager = require(Modules:FindFirstChild('AccountManager'))
local AssetManager = require(Modules:FindFirstChild('AssetManager'))
local BaseSignInScreen = require(Modules:FindFirstChild('BaseSignInScreen'))
local Errors = require(Modules:FindFirstChild('Errors'))
local ErrorOverlay = require(Modules:FindFirstChild('ErrorOverlay'))
local GlobalSettings = require(Modules:FindFirstChild('GlobalSettings'))
local LoadingWidget = require(Modules:FindFirstChild('LoadingWidget'))
local ScreenManager = require(Modules:FindFirstChild('ScreenManager'))
local SoundManager = require(Modules:FindFirstChild('SoundManager'))
local Strings = require(Modules:FindFirstChild('LocalizedStrings'))
local TextBox = require(Modules:FindFirstChild('TextBox'))
local Utility = require(Modules:FindFirstChild('Utility'))
local UserData = require(Modules:FindFirstChild('UserData'))

local function createSetAccountCredentialsScreen()
	local this = BaseSignInScreen()

	this:SetTitle(string.upper(Strings:LocalizedString("SignUpTitle")))
	this:SetDescriptionText(Strings:LocalizedString("SignUpPhrase"))
	this:SetButtonText(Strings:LocalizedString("SignUpWord"))

	local ModalOverlay = Utility.Create'Frame'
	{
		Name = "ModalOverlay";
		Size = UDim2.new(1, 0, 1, 0);
		BackgroundTransparency = GlobalSettings.ModalBackgroundTransparency;
		BackgroundColor3 = GlobalSettings.ModalBackgroundColor;
		BorderSizePixel = 0;
		ZIndex = 4;
	}

	local myUsername = nil
	local myPassword = nil

	local isUsernameValid = false
	local isPasswordValid = false

	this.UsernameObject:SetDefaultText(Strings:LocalizedString("UsernameWord").." ("..
		Strings:LocalizedString("UsernameRulePhrase")..")")
	this.UsernameObject:SetKeyboardTitle(Strings:LocalizedString("UsernameWord"))
	this.UsernameObject:SetKeyboardDescription(Strings:LocalizedString("UsernameRulePhrase"))
	local usernameChangedCn = nil

	this.PasswordObject:SetDefaultText(Strings:LocalizedString("PasswordWord").." ("..
		Strings:LocalizedString("PasswordRulePhrase")..")")
	this.PasswordObject:SetKeyboardTitle(Strings:LocalizedString("PasswordWord"))
	this.PasswordObject:SetKeyboardDescription(Strings:LocalizedString("PasswordRulePhrase"))
	this.PasswordObject:SetKeyboardType(Enum.XboxKeyBoardType.Password)
	local passwordChangedCn = nil

	local function SetCredentialsAsync()
		local setCredentialsResult = nil
		local function setCredentials()
			setCredentialsResult = AccountManager:SetRobloxCredentialsAsync(myUsername, myPassword)
		end

		local loader = LoadingWidget(
			{ Parent = ModalOverlay }, { setCredentials })

		-- set up full screen loader
		ModalOverlay.Parent = GuiRoot
		ContextActionService:BindCoreAction("BlockB", function() end, false, Enum.KeyCode.ButtonB)
		local selectedObject = GuiService.SelectedCoreObject
		GuiService.SelectedCoreObject = nil

		-- call loader
		loader:AwaitFinished()

		-- clean up
		loader:Cleanup()
		loader = nil
		GuiService.SelectedCoreObject = selectedObject
		ContextActionService:UnbindCoreAction("BlockB")
		ModalOverlay.Parent = nil

		if setCredentialsResult == AccountManager.AuthResults.Success then
			UserData:SetHasRobloxCredentials(true)
			ScreenManager:CloseCurrent()
		else
			local err = setCredentialResult and Errors.Authentication[setCredentialResult] or Errors.Default
			ScreenManager:OpenScreen(ErrorOverlay(err), false)
		end
	end

	local isSettingCredentials = false
	this.SignInButton.MouseButton1Click:connect(function()
		if isSettingCredentials then return end
		isSettingCredentials = true

		SoundManager:Play('ButtonPress')
		if isUsernameValid and isPasswordValid then
			SetCredentialsAsync()
		else
			local err = Errors.SignIn.NoUsernameOrPasswordEntered
			ScreenManager:OpenScreen(ErrorOverlay(err), false)
		end
		isSettingCredentials = false
	end)

	local function validatePassword()
		local reason = nil
		isPasswordValid, reason = AccountManager:IsValidPasswordAsync(myUsername or "", myPassword)
		if isPasswordValid then
			if myUsername and #myUsername > 0 then
				GuiService.SelectedCoreObject = this.SignInButton
			else
				GuiService.SelectedCoreObject = this.UsernameSelection
			end
		else
			-- web returns long strings on password error. Lets create our own error type
			GuiService.SelectedCoreObject = this.PasswordSelection
			local err = reason and { Title = Strings:LocalizedString("InvalidPasswordTitle"), Msg = reason } or Errors.Default
			ScreenManager:OpenScreen(ErrorOverlay(err), false)
		end
	end

	local function onUsernameChanged(text)
		myUsername = text
		if #myUsername > 0 then
			-- 1. Check if valid user name
			local reason = nil
			isUsernameValid, reason = AccountManager:IsValidUsernameAsync(myUsername)
			if isUsernameValid then
				-- 2. if password set, need to recheck password rules
				if myPassword and #myPassword > 0 then
					validatePassword()
				else
					GuiService.SelectedCoreObject = this.PasswordSelection
				end
			else
				GuiService.SelectedCoreObject = this.UsernameSelection
				local err = Errors.SignIn[reason] or Errors.Default
				ScreenManager:OpenScreen(ErrorOverlay(err), false)
			end
		else
			GuiService.SelectedCoreObject = this.UsernameSelection
			isUsernameValid = false
		end
	end

	local function onPasswordChanged(text)
		myPassword = text
		if #myPassword > 0 then
			validatePassword()
		else
			GuiService.SelectedCoreObject = this.PasswordSelection
			isPasswordValid = false
		end
	end

	--[[ Public API ]]--
	-- override
	local baseFocus = this.Focus
	function this:Focus()
		baseFocus(self)
		usernameChangedCn = this.UsernameObject.OnTextChanged:connect(onUsernameChanged)
		passwordChangedCn = this.PasswordObject.OnTextChanged:connect(onPasswordChanged)
	end

	-- override
	local baseRemoveFocus = this.RemoveFocus
	function this:RemoveFocus()
		baseRemoveFocus(self)
		Utility.DisconnectEvent(usernameChangedCn)
		Utility.DisconnectEvent(passwordChangedCn)
	end

	return this
end

return createSetAccountCredentialsScreen
