--[[
			// AccountManager.lua

			// Handles all account related functions
]]
local CoreGui = Game:GetService("CoreGui")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")

local PlatformService = game:GetService('PlatformService')
local UserInputService = game:GetService('UserInputService')

local Http = require(Modules:FindFirstChild('Http'))
local Utility = require(Modules:FindFirstChild('Utility'))

local AccountLinkingEnabled = Utility.IsFastFlagEnabled("AccountLinkEnabled")

local AccountManager = {}

AccountManager.AuthResults = {
	Error = -1;
	Success = 0;
	InProgress = 1;
	AccountUnlinked = 2;
	MissingGamePad = 3;
	NoUserDetected = 4;
	HttpErrorDetected = 5;
	SignUpDisabled = 6;
	Flooded = 7;
	LeaseLocked = 8;
	AccountLinkingDisabled = 9;
	InvalidRobloxUser = 10;
	RobloxUserAlreadyLinked = 11;
	XboxUserAlreadyLinked = 12;
	IllgealChildAccountLinking = 13;
	InvalidPassword = 14;
	UsernamePasswordNotSet = 15;
	UsernameAlreadyTaken = 16;
}

AccountManager.InvalidUsernameReasons = {
	Valid = "Valid";
	InvalidUsername = "Invalid Username";
	AlreadyTaken = "Already Taken";
	InvalidCharactersUsed = "Invalid Characters Used";
	UsernameCannotContainSpaces = "Username Cannot Contain Spaces";
}

--[[ Authentication ]]--
local function authenticateStudio()
	return AccountManager.AuthResults.Success
end

-- TODO: Auth will now return an int that maps to a success or failure
-- Getting the GamerTag and rbxUid will be a seperate call after auth
local function authenticateXBox(inputObject)
	local authResult = nil
	local success, result = pcall(function()
		if AccountLinkingEnabled then
			authResult = PlatformService:BeginAuthUnlinkCheck(inputObject)
		else
			authResult = PlatformService:BeginAuthorization(inputObject)
		end
	end)
	if success and not AccountLinkingEnabled then
		-- unlinked success is pcall success, set result to success code
		authResult = AccountManager.AuthResults.Success
	end

	return authResult
end

function AccountManager:SignInAsync(inputObject)
	local success, result = pcall(function()
		return PlatformService:BeginAuthorization(inputObject)
	end)
	if success then
		return AccountManager.AuthResults.Success
	else
		return AccountManager.AuthResults.Error
	end
end

-- Returns
	-- Success of authentication, with authentication state
function AccountManager:BeginAuthenticationAsync(inputObject)
	local result = nil
	if UserSettings().GameSettings:InStudioMode() then
		result = authenticateStudio()
	elseif PlatformService and UserInputService:GetPlatform() == Enum.Platform.XBoxOne then
		result = authenticateXBox(inputObject)
	end

	return result
end

--[[ Account Linking ]]--
-- called at sign in
function AccountManager:LinkAccountAsync(accountName, password)
	local success, result = pcall(function()
		return PlatformService:BeginAccountLink(accountName, password)
	end)
	if not success then
		print("AccountManager:LinkAccountAsync() failed because", result)
		result = nil
	end

	return result
end

-- used when setting credentials for a generated account
function AccountManager:SetRobloxCredentialsAsync(accountName, password)
	local success, result = pcall(function()
		return PlatformService:BeginSetRobloxCredentials(accountName, password)
	end)
	if not success then
		print("AccountManager:SetRobloxCredentialsAsync() failed because", result)
		result = nil
	end

	return result
end

-- called when user has roblox credentials
function AccountManager:UnlinkAccountAsync()
	local success, result = pcall(function()
		return PlatformService:BeginUnlinkAccount()
	end)
	if not success then
		print("AccountManager:UnlinkAccountAsync() failed because", result)
		result = nil
	end

	return result
end

function AccountManager:HasLinkedAccountAsync()
	if UserSettings().GameSettings:InStudioMode() then
		return true
	end

	local success, result = pcall(function()
		return PlatformService:BeginHasLinkedAccount()
	end)
	if not success then
		print("AccountManager:HasLinkedAccountAsync() failed because", result)
		result = nil
	end

	return result
end

function AccountManager:HasRobloxCredentialsAsync()
	if UserSettings().GameSettings:InStudioMode() then
		return true
	end

	local success, result = pcall(function()
		return PlatformService:BeginHasRobloxCredentials()
	end)
	if not success then
		print("AccountManager:HasRobloxCredentialsAsync() failed because", result)
		result = nil
	end

	return result
end

function AccountManager:IsValidUsernameAsync(username)
	local result = Http.IsValidUsername(username)
	if not result then
		return false
	end

	return result["IsValid"], result["ErrorMessage"]
end

function AccountManager:IsValidPasswordAsync(username, password)
	local result = Http.IsValidPassword(username, password)
	if not result then
		return false
	end

	return result["IsValid"], result["ErrorMessage"]
end

return AccountManager
