class InspectionEvent extends Event
{
	var enabled : Bool;
}

class InspectionComponent extends ScriptableComponent
{
	editable var m_slot : String;
	private var m_cumulatedObjRotationX : Float;
	private var m_cumulatedObjRotationY : Float;
	private var m_maxObjOffset : Float;
	private var m_minObjOffset : Float;
	private var m_zoomSpeed : Float;
	private var m_timeToScan : Float;
	private var m_isPlayerInspecting : Bool;
	private var m_activeClue : String;
	private var m_isScanAvailable : Bool;
	private var m_scanningInProgress : Bool;
	private var m_objectScanned : Bool;
	private var m_animFeature : AnimFeature_Inspection;
	private var m_listener : IScriptable;
	private var m_lastInspectedObjID : EntityID;

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		m_animFeature = new AnimFeature_Inspection;
	}

	protected event OnInspectionEvent( evt : InspectionEvent )
	{
		if( !( evt.enabled ) )
		{
			ExitInspect();
		}
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( m_isPlayerInspecting )
		{
			if( ListenerAction.GetName( action ) == 'InspectionTake' )
			{
				LootInspectItem();
			}
			if( ListenerAction.GetName( action ) == 'InspectionZoom' )
			{
				ProcessZoom( ListenerAction.GetValue( action ) );
			}
			if( ( ListenerAction.GetName( action ) == 'InspectionScan' && ListenerAction.IsButtonJustPressed( action ) ) && m_isScanAvailable )
			{
				ScanInspectableItem();
				DisplayScanningUI( true );
			}
			if( ListenerAction.GetName( action ) == 'RotateObjectX' )
			{
				RotateInInspection( ListenerAction.GetValue( action ), 0.0 );
			}
			if( ListenerAction.GetName( action ) == 'RotateObjectY' )
			{
				RotateInInspection( 0.0, ListenerAction.GetValue( action ) );
			}
			if( ListenerAction.GetName( action ) == 'RotateObjectX_Mouse' )
			{
				RotateInInspectionByMouse( ListenerAction.GetValue( action ), 0.0 );
			}
			if( ListenerAction.GetName( action ) == 'RotateObjectY_Mouse' )
			{
				RotateInInspectionByMouse( 0.0, ListenerAction.GetValue( action ) );
			}
		}
	}

	private function RotateInInspection( deltaX : Float, deltaY : Float )
	{
		m_cumulatedObjRotationX += ( 5.0 * deltaX );
		m_cumulatedObjRotationX = AngleNormalize180( m_cumulatedObjRotationX );
		m_cumulatedObjRotationY += ( 5.0 * deltaY );
		m_cumulatedObjRotationY = AngleNormalize180( m_cumulatedObjRotationY );
		m_animFeature.rotationX = m_cumulatedObjRotationX;
		m_animFeature.rotationY = m_cumulatedObjRotationY;
		AnimationControllerComponent.ApplyFeature( GetOwner(), 'Inspection', m_animFeature );
	}

	private function RotateInInspectionByMouse( deltaX : Float, deltaY : Float )
	{
		var x_axis : Float;
		var y_axis : Float;
		x_axis = deltaX / 20.0;
		y_axis = deltaY / 20.0;
		RotateInInspection( x_axis, y_axis );
	}

	private function ProcessZoom( val : Float )
	{
		m_animFeature.offsetY = LerpF( val, m_maxObjOffset, m_minObjOffset );
		AnimationControllerComponent.ApplyFeature( GetOwner(), 'Inspection', m_animFeature );
	}

	private function ToggleInspection( enabled : Bool )
	{
		SetInputListening( enabled );
		if( enabled )
		{
			m_listener = this;
		}
		else
		{
			m_listener = NULL;
		}
	}

	protected event OnInspectTrigger( evt : InspectionTriggerEvent )
	{
		SetIsPlayerInspecting( true );
		ToggleInspection( m_isPlayerInspecting );
		if( EntityID.IsDefined( evt.inspectedObjID ) )
		{
			SetLastInspectedObjectID( evt.inspectedObjID );
		}
		PlaceItemInInspectSlot( evt.item, evt.offset );
		SetObjectOffsets( evt.offset, evt.adsOffset );
		SetTimeToScan( evt.timeToScan );
	}

	protected event OnPreScanEvent( evt : ScanEvent )
	{
		if( evt.clue != "" )
		{
			m_isScanAvailable = evt.isAvailable;
			m_activeClue = evt.clue;
		}
	}

	private function DisplayScanningUI( show : Bool )
	{
		var evt : TEMP_ScanningEvent;
		var item : GameObject;
		item = GetTransactionSystem().GetItemInSlot( GetOwner(), TDBID.Create( m_slot ) );
		evt = new TEMP_ScanningEvent;
		evt.showUI = show;
		item.QueueEvent( evt );
	}

	private function ScanInspectableItem()
	{
		m_scanningInProgress = true;
	}

	private function OnUpdate( deltaTime : Float )
	{
		if( m_scanningInProgress && !( m_objectScanned ) )
		{
			m_timeToScan -= deltaTime;
			if( ( m_timeToScan <= 0.0 ) && m_isScanAvailable )
			{
				m_scanningInProgress = false;
				m_objectScanned = true;
				DisplayScanningUI( false );
				GameInstance.GetQuestsSystem( GetOwner().GetGame() ).SetFactStr( "inspected_" + m_activeClue, 1 );
			}
		}
	}

	private function SetObjectOffsets( offset : Float, adsOffset : Float )
	{
		m_minObjOffset = adsOffset;
		m_maxObjOffset = offset;
	}

	private function SetTimeToScan( timeVal : Float )
	{
		m_timeToScan = timeVal;
	}

	private function SetInputListening( enabled : Bool )
	{
		if( enabled && !( m_listener ) )
		{
			GetOwner().RegisterInputListener( this, 'InspectionTake' );
			GetOwner().RegisterInputListener( this, 'InspectionZoom' );
			GetOwner().RegisterInputListener( this, 'InspectionScan' );
			GetOwner().RegisterInputListener( this, 'RotateObjectX' );
			GetOwner().RegisterInputListener( this, 'RotateObjectY' );
			GetOwner().RegisterInputListener( this, 'RotateObjectX_Mouse' );
			GetOwner().RegisterInputListener( this, 'RotateObjectX_Mouse' );
		}
		else if( m_listener )
		{
			GetOwner().UnregisterInputListener( this );
		}
	}

	private function ResetScanningState()
	{
		m_scanningInProgress = false;
		m_isScanAvailable = false;
		SetTimeToScan( 0.0 );
	}

	private function ExitInspect()
	{
		var item : GameObject;
		var transSystem : TransactionSystem;
		transSystem = GameInstance.GetTransactionSystem( GetOwner().GetGame() );
		item = transSystem.GetItemInSlot( GetOwner(), TDBID.Create( m_slot ) );
		if( item != NULL )
		{
			ToggleInspectObject( true );
		}
		ToggleExitInspect();
	}

	private function ToggleExitInspect()
	{
		var inspectStateEvt : SetInspectStateEvent;
		var id : PersistentID;
		RemoveInspectedItem();
		SetIsPlayerInspecting( false );
		SetInspectionStage( 0 );
		ResetScanningState();
		ToggleInspection( m_isPlayerInspecting );
		id = CreatePersistentID( m_lastInspectedObjID, 'inspectComponent' );
		inspectStateEvt = new SetInspectStateEvent;
		inspectStateEvt.state = questObjectInspectEventType.Finished;
		GameInstance.GetPersistencySystem( GetOwner().GetGame() ).QueuePSEvent( id, 'InspectableObjectComponentPS', inspectStateEvt );
	}

	private function LootInspectItem()
	{
		EmptyInspectSlot();
		ToggleInspectObject( false );
		ToggleExitInspect();
	}

	private function ToggleInspectObject( show : Bool )
	{
		var evt : ObjectInspectEvent;
		evt = new ObjectInspectEvent;
		evt.showItem = show;
		GetOwner().QueueEventForEntityID( m_lastInspectedObjID, evt );
	}

	private function PlaceItemInInspectSlot( const itemTDBIDString : ref< String >, offset : Float )
	{
		var owner : PlayerPuppet;
		var transSystem : TransactionSystem;
		var itemTDBID : TweakDBID;
		var itemID : ItemID;
		owner = ( ( PlayerPuppet )( GetOwner() ) );
		itemTDBID = TDBID.Create( itemTDBIDString );
		itemID = ItemID.FromTDBID( itemTDBID );
		transSystem = GameInstance.GetTransactionSystem( owner.GetGame() );
		transSystem.GiveItem( owner, itemID, 1 );
		transSystem.AddItemToSlot( owner, TDBID.Create( m_slot ), itemID );
		ResetAnimFeature();
		m_animFeature.offsetY = offset;
		AnimationControllerComponent.ApplyFeature( GetOwner(), 'Inspection', m_animFeature );
		SetInspectionStage( 1 );
	}

	private function CleanupInspectSlot( wasLooted : Bool )
	{
		if( wasLooted )
		{
			EmptyInspectSlot();
		}
		else
		{
			RemoveInspectedItem();
		}
	}

	private function EmptyInspectSlot()
	{
		var transSystem : TransactionSystem;
		transSystem = GameInstance.GetTransactionSystem( GetOwner().GetGame() );
		transSystem.RemoveItemFromSlot( GetOwner(), TDBID.Create( m_slot ) );
	}

	private function RemoveInspectedItem()
	{
		var itemInSlot : ItemID;
		var owner : GameObject;
		var transSystem : TransactionSystem;
		owner = GetOwner();
		transSystem = GameInstance.GetTransactionSystem( owner.GetGame() );
		itemInSlot = ( ( ItemObject )( transSystem.GetItemInSlot( owner, TDBID.Create( m_slot ) ) ) ).GetItemID();
		if( ItemID.IsValid( itemInSlot ) == false )
		{
			return;
		}
		transSystem.RemoveItem( owner, itemInSlot, 1 );
	}

	private function ResetAnimFeature()
	{
		m_cumulatedObjRotationX = 0.0;
		m_cumulatedObjRotationY = 0.0;
		m_animFeature.rotationX = 0.0;
		m_animFeature.rotationY = 0.0;
		AnimationControllerComponent.ApplyFeature( GetOwner(), 'Inspection', m_animFeature );
	}

	private function SetInspectionStage( stage : Int32 )
	{
		m_animFeature.activeInspectionStage = stage;
		AnimationControllerComponent.ApplyFeature( GetOwner(), 'Inspection', m_animFeature );
	}

	public const function GetIsPlayerInspecting() : Bool
	{
		return m_isPlayerInspecting;
	}

	private function SetIsPlayerInspecting( enabled : Bool )
	{
		m_isPlayerInspecting = enabled;
	}

	public const function GetLastInspectedObjectID() : EntityID
	{
		return m_lastInspectedObjID;
	}

	private function SetLastInspectedObjectID( newID : EntityID )
	{
		m_lastInspectedObjID = newID;
	}

	private function RememberInspectedObjID( id : EntityID )
	{
		m_lastInspectedObjID = id;
	}

}

