class TimeDilationParameters extends IScriptable
{
	var reason : CName;
	var timeDilation : Float;
	default timeDilation = 0.01f;
	var playerTimeDilation : Float;
	default playerTimeDilation = 0.01f;
	var duration : Float;
	default duration = 9999.0f;
	var easeInCurve : CName;
	var easeOutCurve : CName;
}

class TimeDilationHelper
{

	public static function GetTimeDilationParameters( out timeDilationParameters : TimeDilationParameters, const profileName : ref< String > )
	{
		timeDilationParameters = new TimeDilationParameters;
		timeDilationParameters.reason = TimeDilationHelper.GetCNameFromTimeSystemTweak( profileName, "reason" );
		timeDilationParameters.timeDilation = TimeDilationHelper.GetFloatFromTimeSystemTweak( profileName, "timeDilation" );
		timeDilationParameters.playerTimeDilation = TimeDilationHelper.GetFloatFromTimeSystemTweak( profileName, "playerTimeDilation" );
		timeDilationParameters.duration = TimeDilationHelper.GetFloatFromTimeSystemTweak( profileName, "duration" );
		timeDilationParameters.easeInCurve = TimeDilationHelper.GetCNameFromTimeSystemTweak( profileName, "easeInCurve" );
		timeDilationParameters.easeOutCurve = TimeDilationHelper.GetCNameFromTimeSystemTweak( profileName, "easeOutCurve" );
	}

	public static function SetTimeDilationWithProfile( requester : weak< GameObject >, const profileName : ref< String >, enable : Bool, allowMultipleTimeDilationSimultaneously : Bool ) : Bool
	{
		var timeDilationParameters : TimeDilationParameters;
		var reason : CName;
		var timeDilation : Float;
		var playerTimeDilation : Float;
		var duration : Float;
		var easeInCurve : CName;
		var easeOutCurve : CName;
		var timeSystem : TimeSystem;
		var isTimeDilationActive : Bool;
		if( !( requester ) )
		{
			return false;
		}
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( !( timeSystem ) )
		{
			return false;
		}
		isTimeDilationActive = timeSystem.IsTimeDilationActive();
		if( ( ( !( enable ) && !( isTimeDilationActive ) ) || ( ( !( allowMultipleTimeDilationSimultaneously ) && enable ) && isTimeDilationActive ) ) || IsMultiplayer() )
		{
			return false;
		}
		TimeDilationHelper.GetTimeDilationParameters( timeDilationParameters, profileName );
		reason = timeDilationParameters.reason;
		timeDilation = timeDilationParameters.timeDilation;
		playerTimeDilation = timeDilationParameters.playerTimeDilation;
		duration = timeDilationParameters.duration;
		easeInCurve = timeDilationParameters.easeInCurve;
		easeOutCurve = timeDilationParameters.easeOutCurve;
		if( enable )
		{
			SetTimeDilation( requester, reason, timeDilation, duration, easeInCurve, easeOutCurve, allowMultipleTimeDilationSimultaneously );
			SetTimeDilationOnPlayer( requester, reason, playerTimeDilation, duration, easeInCurve, easeOutCurve, allowMultipleTimeDilationSimultaneously );
		}
		else
		{
			UnSetTimeDilation( requester, reason, easeOutCurve );
			UnSetTimeDilationOnPlayer( requester, reason, easeOutCurve );
		}
		return true;
	}

	public static function SetTimeDilation( requester : weak< GameObject >, reason : CName, timeDilation : Float, optional duration : Float, easeInCurve : CName, easeOutCurve : CName, allowMultipleTimeDilationSimultaneously : Bool, optional listener : TimeDilationListener ) : Bool
	{
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( ( !( timeSystem ) || ( !( allowMultipleTimeDilationSimultaneously ) && timeSystem.IsTimeDilationActive() ) ) || IsMultiplayer() )
		{
			return false;
		}
		timeSystem.SetTimeDilation( reason, timeDilation, duration, easeInCurve, easeOutCurve, listener );
		return true;
	}

	public static function SetTimeDilationOnPlayer( requester : weak< GameObject >, reason : CName, timeDilation : Float, optional duration : Float, easeInCurve : CName, easeOutCurve : CName, allowMultipleTimeDilationSimultaneously : Bool, optional listener : TimeDilationListener ) : Bool
	{
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( ( !( timeSystem ) || ( !( allowMultipleTimeDilationSimultaneously ) && timeSystem.IsTimeDilationActive() ) ) || IsMultiplayer() )
		{
			return false;
		}
		SetIgnoreTimeDilationOnLocalPlayerZero( requester, false );
		timeSystem.SetTimeDilationOnLocalPlayerZero( reason, timeDilation, duration, easeInCurve, easeOutCurve );
		return true;
	}

	public static function UnSetTimeDilation( requester : weak< GameObject >, optional reason : CName, optional easeOutCurve : CName ) : Bool
	{
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( ( !( timeSystem ) || !( timeSystem.IsTimeDilationActive() ) ) || IsMultiplayer() )
		{
			return false;
		}
		if( !( IsNameValid( easeOutCurve ) ) )
		{
			timeSystem.UnsetTimeDilation( reason, '' );
		}
		else
		{
			timeSystem.UnsetTimeDilation( reason, easeOutCurve );
		}
		return true;
	}

	public static function UnSetTimeDilationOnPlayer( requester : weak< GameObject >, optional reason : CName, optional easeOutCurve : CName ) : Bool
	{
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( !( timeSystem ) || IsMultiplayer() )
		{
			return false;
		}
		if( !( IsNameValid( easeOutCurve ) ) )
		{
			timeSystem.UnsetTimeDilationOnLocalPlayerZero( reason, '' );
		}
		else
		{
			timeSystem.UnsetTimeDilationOnLocalPlayerZero( reason, easeOutCurve );
		}
		RestorePreviousIgnoreTimeDilationOnLocalPlayerZero( requester );
		return true;
	}

	public static function SetIgnoreTimeDilationOnLocalPlayerZero( requester : weak< GameObject >, ignore : Bool ) : Bool
	{
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( !( timeSystem ) || IsMultiplayer() )
		{
			return false;
		}
		timeSystem.SetIgnoreTimeDilationOnLocalPlayerZero( ignore );
		return true;
	}

	public static function RestorePreviousIgnoreTimeDilationOnLocalPlayerZero( requester : weak< GameObject > ) : Bool
	{
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( requester.GetGame() );
		if( !( timeSystem ) || IsMultiplayer() )
		{
			return false;
		}
		timeSystem.RestorePreviousIgnoreTimeDilationOnLocalPlayerZero();
		return true;
	}

	public static function SetIndividualTimeDilation( target : weak< GameObject >, reason : CName, timeDilation : Float, optional duration : Float, optional easeInCurve : CName, optional easeOutCurve : CName ) : Bool
	{
		if( IsMultiplayer() )
		{
			return false;
		}
		( ( gamePuppet )( target ) ).SetIndividualTimeDilation( reason, timeDilation, duration, easeInCurve, easeOutCurve );
		return true;
	}

	public static function UnsetIndividualTimeDilation( target : weak< GameObject >, optional easeOutCurve : CName ) : Bool
	{
		if( IsMultiplayer() )
		{
			return false;
		}
		( ( gamePuppet )( target ) ).UnsetIndividualTimeDilation( easeOutCurve );
		return true;
	}

	public static function CanUseTimeDilation( playerGameObject : weak< GameObject > ) : Bool
	{
		var playerVehicleState : Int32;
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( playerGameObject ) );
		if( !( player ) )
		{
			return false;
		}
		playerVehicleState = player.GetPlayerStateMachineBlackboard().GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vehicle );
		if( playerVehicleState != ( ( Int32 )( gamePSMVehicle.Default ) ) )
		{
			if( ( ( playerVehicleState != ( ( Int32 )( gamePSMVehicle.Driving ) ) ) && ( playerVehicleState != ( ( Int32 )( gamePSMVehicle.DriverCombat ) ) ) ) && ( playerVehicleState != ( ( Int32 )( gamePSMVehicle.Transition ) ) ) )
			{
				return false;
			}
			if( !( PlayerDevelopmentSystem.GetData( player ).IsNewPerkBoughtAnyLevel( gamedataNewPerkType.Cool_Left_Milestone_1 ) ) )
			{
				return false;
			}
		}
		if( GameInstance.GetStatusEffectSystem( playerGameObject.GetGame() ).HasStatusEffect( playerGameObject.GetEntityID(), T"BaseStatusEffect.PlayerInFinisherWorkspot" ) )
		{
			return false;
		}
		return true;
	}

	public static function GetFloatFromTimeSystemTweak( const tweakDBPath : ref< String >, const paramName : ref< String > ) : Float
	{
		return TDB.GetFloat( TDBID.Create( ( ( "timeSystem." + tweakDBPath ) + "." ) + paramName ), 0.0 );
	}

	public static function GetCNameFromTimeSystemTweak( const tweakDBPath : ref< String >, const paramName : ref< String > ) : CName
	{
		return TDB.GetCName( TDBID.Create( ( ( "timeSystem." + tweakDBPath ) + "." ) + paramName ), '' );
	}

	public constexpr static function GetTimeDilationKey() : CName
	{
		return 'timeDilation';
	}

	public constexpr static function GetSandevistanKey() : CName
	{
		return 'sandevistan';
	}

	public constexpr static function GetSandevistanVersusSandevistanKey() : CName
	{
		return 'sandevistanVersusSandevistan';
	}

	public constexpr static function GetKerenzikovKey() : CName
	{
		return 'kereznikov';
	}

	public constexpr static function GetFocusModeKey() : CName
	{
		return 'focusMode';
	}

	public constexpr static function GetFocusedStateKey() : CName
	{
		return 'focusedStatePerkDilation';
	}

}

