--MasterControl needs access to ControlState in order to be able to fully enable and disable control
MasterControl.ControlState = ControlState

local DynamicThumbstickModule = require(script.MasterControl:WaitForChild('DynamicThumbstick'))
local ThumbstickModule = require(script.MasterControl:WaitForChild('Thumbstick'))
local ThumbpadModule = require(script.MasterControl:WaitForChild('Thumbpad'))
local DPadModule = require(script.MasterControl:WaitForChild('DPad'))
local DefaultModule = ControlModules.Thumbstick
local TouchJumpModule = require(script.MasterControl:WaitForChild('TouchJump'))
local ClickToMoveModule = FFlagUserNoCameraClickToMove and require(script.MasterControl:WaitForChild('ClickToMoveController')) or nil

MasterControl.TouchJumpModule = TouchJumpModule
local VRNavigationModule = require(script.MasterControl:WaitForChild('VRNavigation'))
local keyboardModule = require(script.MasterControl:WaitForChild('KeyboardMovement'))
ControlModules.Gamepad = require(script.MasterControl:WaitForChild('Gamepad'))

function getTouchModule()

	local module = nil
	if not IsUserChoice then
		if DynamicThumbstickAvailable and DevMovementMode == Enum.DevTouchMovementMode.DynamicThumbstick then
			module = DynamicThumbstickModule
			isJumpEnabled = false
		elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbstick then
			module = ThumbstickModule
			isJumpEnabled = true
		elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbpad then
			module = ThumbpadModule
			isJumpEnabled = true
		elseif DevMovementMode == Enum.DevTouchMovementMode.DPad then
			module = DPadModule
			isJumpEnabled = false
		elseif DevMovementMode == Enum.DevTouchMovementMode.ClickToMove then
			if FFlagUserNoCameraClickToMove then
				module = ClickToMoveModule
				isJumpEnabled = false -- TODO: What should this be, true or false?
			else
				module = nil
			end
		elseif DevMovementMode == Enum.DevTouchMovementMode.Scriptable then
			module = nil
		end
	else
		if DynamicThumbstickAvailable and UserMovementMode == Enum.TouchMovementMode.DynamicThumbstick then
			module = DynamicThumbstickModule
			isJumpEnabled = false
		elseif UserMovementMode == Enum.TouchMovementMode.Default or UserMovementMode == Enum.TouchMovementMode.Thumbstick then
			module = ThumbstickModule
			isJumpEnabled = true
		elseif UserMovementMode == Enum.TouchMovementMode.Thumbpad then
			module = ThumbpadModule
			isJumpEnabled = true
		elseif UserMovementMode == Enum.TouchMovementMode.DPad then
			module = DPadModule
			isJumpEnabled = false
		elseif UserMovementMode == Enum.TouchMovementMode.ClickToMove then
			if FFlagUserNoCameraClickToMove then
				module = ClickToMoveModule
				isJumpEnabled = false -- TODO: What should this be, true or false?
			else
				module = nil
			end
		end
	end
	return module
end

function setJumpModule(isEnabled)
	if not isEnabled then
		TouchJumpModule:Disable()
	elseif ControlState.Current == ControlModules.Touch then
		TouchJumpModule:Enable()
	end
end

function setClickToMove()
	if DevMovementMode == Enum.DevTouchMovementMode.ClickToMove or DevMovementMode == Enum.DevComputerMovementMode.ClickToMove or
		UserMovementMode == Enum.ComputerMovementMode.ClickToMove or UserMovementMode == Enum.TouchMovementMode.ClickToMove then
		if lastInputType == Enum.UserInputType.Touch then
			ClickToMoveTouchControls = ControlState.Current
		end
	elseif ClickToMoveTouchControls then
		ClickToMoveTouchControls:Disable()
		ClickToMoveTouchControls = nil
	end
end

ControlModules.Touch = {}
ControlModules.Touch.Current = nil
ControlModules.Touch.LocalPlayerChangedCon = nil
ControlModules.Touch.GameSettingsChangedCon = nil

function ControlModules.Touch:RefreshControlStyle()
	if ControlModules.Touch.Current then
		ControlModules.Touch.Current:Disable()
	end
	setJumpModule(false)
	TouchJumpModule:Disable()
	ControlModules.Touch:Enable()
end
function ControlModules.Touch:DisconnectEvents()
	if ControlModules.Touch.LocalPlayerChangedCon then
		ControlModules.Touch.LocalPlayerChangedCon:disconnect()
		ControlModules.Touch.LocalPlayerChangedCon = nil
	end
	if ControlModules.Touch.GameSettingsChangedCon then
		ControlModules.Touch.GameSettingsChangedCon:disconnect()
		ControlModules.Touch.GameSettingsChangedCon = nil
	end
end
function ControlModules.Touch:Enable()
	DevMovementMode = LocalPlayer.DevTouchMovementMode
	IsUserChoice = DevMovementMode == Enum.DevTouchMovementMode.UserChoice
	if IsUserChoice then
		UserMovementMode = GameSettings.TouchMovementMode
	end

	local newModuleToEnable = getTouchModule()
	if newModuleToEnable then
		setClickToMove()
		setJumpModule(isJumpEnabled)

		newModuleToEnable:Enable()
		ControlModules.Touch.Current = newModuleToEnable

		if isJumpEnabled then TouchJumpModule:Enable() end
	end

	-- This being within the above if statement was causing issues with ClickToMove, which isn't a module within this script.
	ControlModules.Touch:DisconnectEvents()
	ControlModules.Touch.LocalPlayerChangedCon = LocalPlayer:GetPropertyChangedSignal("DevTouchMovementMode"):connect(function()
		ControlModules.Touch:RefreshControlStyle()
	end)
	ControlModules.Touch.GameSettingsChangedCon = GameSettings:GetPropertyChangedSignal("TouchMovementMode"):connect(function()
		ControlModules.Touch:RefreshControlStyle()
	end)
end
function ControlModules.Touch:Disable()
	ControlModules.Touch:DisconnectEvents()

	local newModuleToDisable = getTouchModule()

	if newModuleToDisable == ThumbstickModule or
		newModuleToDisable == DPadModule or
		newModuleToDisable == ThumbpadModule or
		newModuleToDisable == DynamicThumbstickModule then
		newModuleToDisable:Disable()
		setJumpModule(false)
		TouchJumpModule:Disable()
	end

	-- UserMovementMode will still have the previous value at this point
	if FFlagUserNoCameraClickToMove and UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
		ClickToMoveModule:Disable()
	end
end

local function getKeyboardModule()
	-- NOTE: Click to move still uses keyboard. Leaving cases in case this ever changes.
	local whichModule = nil
	if not IsUserChoice then
		if DevMovementMode == Enum.DevComputerMovementMode.KeyboardMouse then
			whichModule = keyboardModule
		elseif DevMovementMode == Enum.DevComputerMovementMode.ClickToMove then
			whichModule = keyboardModule
		end 
	else
		if UserMovementMode == Enum.ComputerMovementMode.KeyboardMouse or UserMovementMode == Enum.ComputerMovementMode.Default then
			whichModule = keyboardModule
		elseif UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
			whichModule = keyboardModule
		end
	end

	return whichModule
end

ControlModules.Keyboard = {}
function ControlModules.Keyboard:RefreshControlStyle()
	ControlModules.Keyboard:Disable()
	ControlModules.Keyboard:Enable()
end
function ControlModules.Keyboard:Enable()
	DevMovementMode = LocalPlayer.DevComputerMovementMode
	IsUserChoice = DevMovementMode == Enum.DevComputerMovementMode.UserChoice
	if IsUserChoice then
		UserMovementMode = GameSettings.ComputerMovementMode
	end

	local newModuleToEnable = getKeyboardModule()
	if newModuleToEnable then
		newModuleToEnable:Enable()
	end

	if FFlagUserNoCameraClickToMove and UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
		ClickToMoveModule:Enable()
	end

	ControlModules.Keyboard:DisconnectEvents()
	ControlModules.Keyboard.LocalPlayerChangedCon = LocalPlayer.Changed:connect(function(property)
		if property == 'DevComputerMovementMode' then
			ControlModules.Keyboard:RefreshControlStyle()
		end
	end)

	ControlModules.Keyboard.GameSettingsChangedCon = GameSettings.Changed:connect(function(property)
		if property == 'ComputerMovementMode' then
			ControlModules.Keyboard:RefreshControlStyle()
		end
	end)
end
function ControlModules.Keyboard:DisconnectEvents()
	if ControlModules.Keyboard.LocalPlayerChangedCon then
		ControlModules.Keyboard.LocalPlayerChangedCon:disconnect()
		ControlModules.Keyboard.LocalPlayerChangedCon = nil
	end
	if ControlModules.Keyboard.GameSettingsChangedCon then
		ControlModules.Keyboard.GameSettingsChangedCon:disconnect()
		ControlModules.Keyboard.GameSettingsChangedCon = nil
	end
end
function ControlModules.Keyboard:Disable()
	ControlModules.Keyboard:DisconnectEvents()
	local newModuleToDisable = getKeyboardModule()
	if newModuleToDisable then
		newModuleToDisable:Disable()
	end

	-- UserMovementMode will still be set to previous movement type
	if FFlagUserNoCameraClickToMove and UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
		ClickToMoveModule:Disable()
	end
end

ControlModules.VRNavigation = {}

function ControlModules.VRNavigation:Enable()
	VRNavigationModule:Enable()
end

function ControlModules.VRNavigation:Disable()
	VRNavigationModule:Disable()
end

if not FFlagUserNoCameraClickToMove and IsTouchDevice then
	BindableEvent_OnFailStateChanged = script.Parent:WaitForChild("OnClickToMoveFailStateChange")
end