class DeviceTimetableEvent extends Event
{
	var state : EDeviceStatus;
	var requesterID : EntityID;
	var restorePower : Bool;
}

struct SSimpleGameTime
{
	[ rangeMin = "0" ][ rangeMax = "23" ]
	instanceeditable persistent var hours : Int32;
	[ rangeMin = "0" ][ rangeMax = "60" ]
	instanceeditable persistent var minutes : Int32;
	[ rangeMin = "0" ][ rangeMax = "60" ]
	instanceeditable persistent var seconds : Int32;
}

struct SDeviceTimetableEntry
{
	instanceeditable persistent var time : SSimpleGameTime;
	instanceeditable persistent var state : EDeviceStatus;
	var entryID : Uint32;
}

class DeviceTimeTableManager extends IScriptable
{
	protected const instanceeditable persistent var m_timeTable : array< SDeviceTimetableEntry >;

	public function InitializeTimetable( owner : GameObject )
	{
		var i : Int32;
		var evt : DeviceTimetableEvent;
		var timeout : GameTime;
		var entryTime : GameTime;
		var currentTime : GameTime;
		var timeSystem : TimeSystem;
		timeSystem = GameInstance.GetTimeSystem( owner.GetGame() );
		currentTime = GetCurrentTime( owner.GetGame() );
		for( i = 0; i < m_timeTable.Size(); i += 1 )
		{
			timeout = GameTime.MakeGameTime( 0, 0, 0, 30 );
			evt = new DeviceTimetableEvent;
			evt.state = m_timeTable[ i ].state;
			evt.requesterID = owner.GetEntityID();
			entryTime = GameTime.MakeGameTime( 0, m_timeTable[ i ].time.hours, m_timeTable[ i ].time.minutes, m_timeTable[ i ].time.seconds );
			timeout += entryTime;
			m_timeTable[ i ].entryID = timeSystem.RegisterIntervalListener( owner, evt, entryTime, timeout, -1 );
			if( ( entryTime != currentTime ) && IsEntryActive( owner.GetGame(), i ) )
			{
				owner.QueueEvent( evt );
			}
		}
	}

	public function IsValid() : Bool
	{
		return m_timeTable.Size() > 0;
	}

	public function UninitializeTimetable( game : GameInstance )
	{
		var i : Int32;
		for( i = 0; i < m_timeTable.Size(); i += 1 )
		{
			GameInstance.GetTimeSystem( game ).UnregisterListener( m_timeTable[ i ].entryID );
		}
	}

	public const function GetTimeTable() : array< SDeviceTimetableEntry >
	{
		return m_timeTable;
	}

	public const function GetDeviceStateForActiveEntry( game : GameInstance ) : EDeviceStatus
	{
		var id : Int32;
		var state : EDeviceStatus;
		id = GetACtiveEntryID( game );
		if( id >= 0 )
		{
			state = m_timeTable[ id ].state;
		}
		return state;
	}

	public const function GetACtiveEntryID( game : GameInstance ) : Int32
	{
		var currentTime : GameTime;
		var entryTime : GameTime;
		var time : GameTime;
		var storedtime : GameTime;
		var i : Int32;
		var id : Int32;
		var wasTimeStored : Bool;
		currentTime = GetCurrentTime( game );
		id = -1;
		for( i = 0; i < m_timeTable.Size(); i += 1 )
		{
			entryTime = GameTime.MakeGameTime( 0, m_timeTable[ i ].time.hours, m_timeTable[ i ].time.minutes, m_timeTable[ i ].time.seconds );
			if( currentTime < entryTime )
			{
				time = ( GameTime.MakeGameTime( 0, 24, 0, 0 ) - entryTime ) + currentTime;
			}
			else
			{
				time = currentTime - entryTime;
			}
			if( ( time < storedtime ) || !( wasTimeStored ) )
			{
				wasTimeStored = true;
				storedtime = time;
				id = i;
			}
		}
		return id;
	}

	private const function IsEntryActive( game : GameInstance, entryID : Int32 ) : Bool
	{
		return GetACtiveEntryID( game ) == entryID;
	}

	private const function GetCurrentTime( game : GameInstance ) : GameTime
	{
		var currentTime : GameTime;
		var time : GameTime;
		currentTime = GameInstance.GetTimeSystem( game ).GetGameTime();
		time = GameTime.MakeGameTime( 0, GameTime.Hours( currentTime ), GameTime.Minutes( currentTime ), GameTime.Seconds( currentTime ) );
		return time;
	}

}

class DeviceTimetable extends ScriptableComponent
{
	instanceeditable inlined var m_timeTableSetup : DeviceTimeTableManager;

	private function OnGameAttach()
	{
		InitializeTimetable();
	}

	private function OnGameDetach()
	{
		UninitializeTimetable();
	}

	public function SetTimetable( timetable : DeviceTimeTableManager )
	{
		m_timeTableSetup = timetable;
		InitializeTimetable();
	}

	private function InitializeTimetable()
	{
		if( m_timeTableSetup != NULL )
		{
			m_timeTableSetup.InitializeTimetable( GetOwner() );
		}
	}

	private function UninitializeTimetable()
	{
		if( m_timeTableSetup != NULL )
		{
			m_timeTableSetup.UninitializeTimetable( GetOwner().GetGame() );
		}
	}

}

