importonly abstract class ISceneSystem extends IGameSystem
{
}

import enum scnFastForwardMode
{
	Default,
	GameplayReview,
}

import enum scnPlayDirection
{
	Forward,
	Backward,
}

import enum scnPlaySpeed
{
	Pause,
	Slow,
	Normal,
	Fast,
	VeryFast,
}

import class scnRewindableSectionEvent extends Event
{
	import var active : Bool;
}

struct SBraindanceInputMask
{
	editable persistent var pauseAction : Bool;
	editable persistent var playForwardAction : Bool;
	editable persistent var playBackwardAction : Bool;
	editable persistent var restartAction : Bool;
	editable persistent var switchLayerAction : Bool;
	editable persistent var cameraToggleAction : Bool;
}

importonly abstract class SceneSystemInterface extends IScriptable
{
	public import function IsFastForwardingAllowed( ffMode : scnFastForwardMode ) : Bool;
	public import function IsFastForwardingActive( ffMode : scnFastForwardMode ) : Bool;
	public import function FastForwardingActivate( ffMode : scnFastForwardMode );
	public import function FastForwardingDeactivate();
	public import function IsRewindableSectionActive() : Bool;
	public import function GetRewindableSectionProgress() : Float;
	public import function GetRewindableSectionTimeInSec() : Float;
	public import function GetRewindableSectionDurationInSec() : Float;
	public import function GetRewindableSectionPlayDirection() : scnPlayDirection;
	public import function SetRewindableSectionPlayDirection( direction : scnPlayDirection );
	public import function GetRewindableSectionPlaySpeed() : scnPlaySpeed;
	public import function SetRewindableSectionPlaySpeed( speed : scnPlaySpeed );
	public import function GetRewindableSectionSpeedModifier() : Float;
	public import function IsRewindableSectionPaused() : Bool;
	public import function ResetRewindableSection( resetSpeed : Float, postResetPlayDirection : scnPlayDirection, postResetPlaySpeed : scnPlaySpeed );
	public import function IsRewindableSectionResetting() : Bool;
	public import function JumpRewindableSection( resetSpeed : Float, jumpTime : Float, postResetPlayDirection : scnPlayDirection, postResetPlaySpeed : scnPlaySpeed ) : Bool;
	public import function SetSceneSystemCameraControlEnabled( enabled : Bool, optional blendTime : Float );
	public import function GetSceneSystemCameraControlEnabled() : Bool;
	public import function GetSceneSystemCameraLastCameraPosition() : WorldPosition;
	public import function GetSceneSystemCameraLastCameraOrientation() : Quaternion;
	public import function AreEntitiesInDialogue( firstEntity : EntityID, secondEntity : EntityID ) : Bool;
	public import function IsEntityInDialogue( entity : EntityID ) : Bool;
	public import function IsEntityInScene( entity : EntityID ) : Bool;
}

importonly abstract class SceneSystem extends ISceneSystem
{
	public import function GetScriptInterface() : SceneSystemInterface;
	public import function GetPeerIdDialogChoiceFactName() : String;
}

class BraindanceSystem extends ScriptableSystem
{
	private persistent var inputMask : SBraindanceInputMask;
	private persistent var requestCameraToggle : Bool;
	private persistent var requestEditorState : Bool;
	private persistent var pauseBraindanceRequest : Bool;
	private persistent var isInBraindance : Bool;
	private var debugFFSceneThrehsold : Int32;

	private export override function IsSavingLocked() : Bool
	{
		return isInBraindance;
	}

	private export function OnPlayerAttach( request : PlayerAttachRequest )
	{
		if( !( isInBraindance ) )
		{
			inputMask.pauseAction = true;
			inputMask.playForwardAction = true;
			inputMask.playBackwardAction = true;
			inputMask.restartAction = true;
			inputMask.switchLayerAction = true;
			inputMask.cameraToggleAction = true;
			requestCameraToggle = false;
			requestEditorState = false;
			pauseBraindanceRequest = false;
			debugFFSceneThrehsold = 3;
		}
	}

	private export override function OnRestored( saveVersion : Int32, gameVersion : Int32 )
	{
		inputMask.pauseAction = true;
		inputMask.playForwardAction = true;
		inputMask.playBackwardAction = true;
		inputMask.restartAction = true;
		inputMask.switchLayerAction = true;
		inputMask.cameraToggleAction = true;
		requestCameraToggle = false;
		requestEditorState = false;
		pauseBraindanceRequest = false;
		debugFFSceneThrehsold = 3;
	}

	public const function GetInputMask() : SBraindanceInputMask
	{
		return inputMask;
	}

	public const function GetRequstCameraToggle() : Bool
	{
		return requestCameraToggle;
	}

	public const function GetRequestEditorState() : Bool
	{
		return requestEditorState;
	}

	public const function GetDebugFFSceneThreshold() : Int32
	{
		return debugFFSceneThrehsold;
	}

	public const function GetIsInBraindance() : Bool
	{
		return isInBraindance;
	}

	public const function GetPauseBraindanceRequest() : Bool
	{
		return pauseBraindanceRequest;
	}

	private function SetInputMask( newMask : SBraindanceInputMask )
	{
		inputMask = newMask;
	}

	private function SetDebugFFSceneThreshold( newThreshold : Int32 )
	{
		debugFFSceneThrehsold = newThreshold;
	}

	private function SetIsInBraindance( newState : Bool )
	{
		isInBraindance = newState;
	}

	private function ApplyORMask( mask : SBraindanceInputMask )
	{
		var globalMask : SBraindanceInputMask;
		var retMask : SBraindanceInputMask;
		globalMask = GetInputMask();
		retMask.pauseAction = mask.pauseAction || globalMask.pauseAction;
		retMask.playForwardAction = mask.playForwardAction || globalMask.playForwardAction;
		retMask.playBackwardAction = mask.playBackwardAction || globalMask.playBackwardAction;
		retMask.restartAction = mask.restartAction || globalMask.restartAction;
		retMask.switchLayerAction = mask.switchLayerAction || globalMask.switchLayerAction;
		retMask.cameraToggleAction = mask.cameraToggleAction || globalMask.cameraToggleAction;
		SetInputMask( retMask );
	}

	private function ApplyInvertedANDMask( mask : SBraindanceInputMask )
	{
		var globalMask : SBraindanceInputMask;
		var retMask : SBraindanceInputMask;
		globalMask = GetInputMask();
		retMask.pauseAction = !( mask.pauseAction ) && globalMask.pauseAction;
		retMask.playForwardAction = !( mask.playForwardAction ) && globalMask.playForwardAction;
		retMask.playBackwardAction = !( mask.playBackwardAction ) && globalMask.playBackwardAction;
		retMask.restartAction = !( mask.restartAction ) && globalMask.restartAction;
		retMask.switchLayerAction = !( mask.switchLayerAction ) && globalMask.switchLayerAction;
		retMask.cameraToggleAction = !( mask.cameraToggleAction ) && globalMask.cameraToggleAction;
		SetInputMask( retMask );
	}

	private function SetEditorStateRequest( newState : Bool )
	{
		requestCameraToggle = true;
		requestEditorState = newState;
	}

	private function ClearEditorStateRequest()
	{
		requestCameraToggle = false;
		requestEditorState = false;
	}

	private function SetPauseRequest()
	{
		pauseBraindanceRequest = true;
	}

	private function ClearPauseRequest()
	{
		pauseBraindanceRequest = false;
	}

	private function OnEnableFields( request : EnableFields )
	{
		ApplyORMask( request.actionMask );
	}

	private function OnDisableFields( request : DisableFields )
	{
		ApplyInvertedANDMask( request.actionMask );
	}

	private function OnSetBraindanceState( request : SetBraindanceState )
	{
		SetEditorStateRequest( request.newState );
	}

	private function OnClearBraindanceStateRequest( request : ClearBraindanceStateRequest )
	{
		ClearEditorStateRequest();
	}

	private function OnSendPauseBraindanceRequest( request : SendPauseBraindanceRequest )
	{
		SetPauseRequest();
	}

	private function OnClearBraindancePauseRequest( request : ClearBraindancePauseRequest )
	{
		ClearPauseRequest();
	}

	private function OnSetDebugSceneThrehsold( request : SetDebugSceneThrehsold )
	{
		SetDebugFFSceneThreshold( request.newThreshold );
	}

	private export function OnSetIsInBraindance( request : SetIsInBraindance )
	{
		SetIsInBraindance( request.newState );
	}

}

class EnableFields extends ScriptableSystemRequest
{
	var actionMask : SBraindanceInputMask;
}

class DisableFields extends ScriptableSystemRequest
{
	var actionMask : SBraindanceInputMask;
}

class SetBraindanceState extends ScriptableSystemRequest
{
	var newState : Bool;
}

class ClearBraindanceStateRequest extends ScriptableSystemRequest
{
}

class SendPauseBraindanceRequest extends ScriptableSystemRequest
{
}

class ClearBraindancePauseRequest extends ScriptableSystemRequest
{
}

class SetDebugSceneThrehsold extends ScriptableSystemRequest
{
	var newThreshold : Int32;
}

class SetIsInBraindance extends ScriptableSystemRequest
{
	var newState : Bool;
}

