class SimpleQuestListItemController extends inkVirtualCompoundItemController
{
	private editable var m_title : inkTextRef;
	private editable var m_description : inkTextRef;
	private editable var m_typeIcon : inkImageRef;
	private editable var m_difficultIcon : inkImageRef;
	private editable var m_fixerIcon : inkImageRef;
	private editable var m_ep1Icon : inkImageRef;
	private editable var m_toggleAnimatedIndicator : inkWidgetRef;
	private editable var m_hoverIndicator : inkWidgetRef;
	private editable var m_questItemFrame : inkWidgetRef;
	private editable var m_questItemBg : inkWidgetRef;
	private editable var m_questItemBgButton : inkWidgetRef;
	private editable var m_distanceContainer : inkWidgetRef;
	private editable var m_defaultDistance : inkTextRef;
	private editable var m_trackedDistance : inkTextRef;
	private editable var m_isNewMarker : inkWidgetRef;
	private editable var m_toggleMarkAnimation : CName;
	private editable var m_trackMarkAnimation : CName;
	private editable var m_distanceAnim_toDefault : CName;
	private editable var m_distanceAnim_toHover : CName;
	private editable var m_distanceAnim_toTracked : CName;
	private editable var m_distanceAnim_toHover_delay : Float;
	default m_distanceAnim_toHover_delay = 0.2f;
	private editable var m_pinIcon_toHover : CName;
	private editable var m_pinIcon_toDefault : CName;
	private var m_toggleOnAnimProxy : inkAnimProxy;
	private var m_toggleOffAnimProxy : inkAnimProxy;
	private var m_pinIconAnimProxy : inkAnimProxy;
	private var m_distanceMarkerAnimProxy : inkAnimProxy;
	private var m_data : QuestListItemData;
	private var m_openedQuest : weak< JournalQuest >;
	private var m_hovered : Bool;
	private var m_toggled : Bool;
	private var m_tracked : Bool;
	private var m_rootWidget : weak< inkWidget >;

	protected event OnInitialize()
	{
		m_rootWidget = GetRootWidget();
		m_rootWidget.SetVAlign( inkEVerticalAlign.Top );
		m_rootWidget.SetHAlign( inkEHorizontalAlign.Left );
		m_rootWidget.RegisterToCallback( 'OnSelected', this, 'OnSelected' );
		m_rootWidget.RegisterToCallback( 'OnDeselected', this, 'OnDeselected' );
		m_rootWidget.RegisterToCallback( 'OnToggledOn', this, 'OnToggledOn' );
		m_rootWidget.RegisterToCallback( 'OnToggledOff', this, 'OnToggledOff' );
		m_rootWidget.RegisterToCallback( 'OnPress', this, 'OnPress' );
		m_rootWidget.RegisterToCallback( 'OnHoverOver', this, 'OnHoverOver' );
		m_rootWidget.RegisterToCallback( 'OnHoverOut', this, 'OnHoverOut' );
		inkWidgetRef.RegisterToCallback( m_distanceContainer, 'OnRelease', this, 'OnTrackBtnRelease' );
		inkWidgetRef.RegisterToCallback( m_distanceContainer, 'OnHoverOver', this, 'OnTrackBtnHoverOver' );
		inkWidgetRef.RegisterToCallback( m_distanceContainer, 'OnHoverOut', this, 'OnTrackBtnHoverOut' );
	}

	protected event OnUnnitialize()
	{
		m_rootWidget.UnregisterFromCallback( 'OnSelected', this, 'OnSelected' );
		m_rootWidget.UnregisterFromCallback( 'OnDeselected', this, 'OnDeselected' );
		m_rootWidget.UnregisterFromCallback( 'OnToggledOn', this, 'OnToggledOn' );
		m_rootWidget.UnregisterFromCallback( 'OnToggledOff', this, 'OnToggledOff' );
		m_rootWidget.UnregisterFromCallback( 'OnPress', this, 'OnPress' );
		inkWidgetRef.UnregisterFromCallback( m_distanceContainer, 'OnRelease', this, 'OnTrackBtnRelease' );
		inkWidgetRef.UnregisterFromCallback( m_distanceContainer, 'OnHoverOver', this, 'OnTrackBtnHoverOver' );
		inkWidgetRef.UnregisterFromCallback( m_distanceContainer, 'OnHoverOut', this, 'OnTrackBtnHoverOut' );
	}

	protected event OnDataChanged( value : Variant )
	{
		var levelDifference : Int32;
		var questType : CName;
		var description : String;
		m_data = ( ( QuestListItemData )( ( ( IScriptable )value ) ) );
		if( m_data.m_isTrackedQuest && !( m_tracked ) )
		{
			m_tracked = true;
			PlayDistanceMarkerAnimation( m_distanceAnim_toTracked, true );
			PlayToggleIconAnimation( true, true );
		}
		else if( !( m_data.m_isTrackedQuest ) && m_tracked )
		{
			m_tracked = false;
			PlayDistanceMarkerAnimation( ( ( m_hovered ) ? ( m_distanceAnim_toHover ) : ( m_distanceAnim_toDefault ) ), , true );
			PlayToggleIconAnimation( false, true );
		}
		questType = QuestTypeIconUtils.GetIconState( m_data.m_questType );
		inkTextRef.SetText( m_title, m_data.m_questData.GetTitle( m_data.m_journalManager ) );
		description = m_data.GetFirstObjective().GetDescription();
		inkTextRef.SetText( m_description, description );
		inkTextRef.SetVisible( m_description, ( ( description == "" ) ? ( false ) : ( true ) ) );
		if( m_data.m_questType == QuestListItemType.Finished )
		{
			inkTextRef.SetVisible( m_description, true );
			inkTextRef.SetText( m_description, ( ( m_data.m_State == gameJournalEntryState.Succeeded ) ? ( "LocKey#27564" ) : ( "LocKey#27566" ) ) );
		}
		inkImageRef.SetVisible( m_ep1Icon, m_data.m_journalManager.IsEp1Entry( m_data.m_questData ) );
		inkImageRef.SetTexturePart( m_typeIcon, QuestTypeIconUtils.GetIcon( m_data.m_questType ) );
		inkImageRef.SetState( m_typeIcon, questType );
		inkWidgetRef.SetState( m_questItemBg, questType );
		inkWidgetRef.SetState( m_hoverIndicator, questType );
		inkWidgetRef.SetState( m_questItemFrame, questType );
		levelDifference = m_data.m_playerLevel - m_data.m_recommendedLevel;
		inkImageRef.SetVisible( m_difficultIcon, levelDifference <= ( ( Int32 )( gameEPowerDifferential.IMPOSSIBLE ) ) );
		UpdateState();
		UpdateFixerData();
		UpdateDistancesText();
		m_data.QuestLastUpdateTime();
	}

	private function UpdateDistancesText()
	{
		var widgetText : String;
		var distance : Float;
		widgetText = "";
		distance = m_data.GetNearestDistance().m_distance;
		if( distance > 0.0 )
		{
			if( distance < 1000.0 )
			{
				widgetText = StrUpper( IntToString( RoundF( distance ) ) + GetLocalizedText( "UI-Labels-Units-Meters" ) );
			}
			else
			{
				distance = RoundTo( distance / 1000.0, 1 );
				widgetText = StrUpper( FloatToStringPrec( distance, 1 ) + GetLocalizedText( "UI-Labels-Units-Kilometers" ) );
			}
			inkTextRef.SetText( m_defaultDistance, widgetText );
			inkTextRef.SetText( m_trackedDistance, widgetText );
			inkTextRef.SetVisible( m_defaultDistance, true );
			inkTextRef.SetVisible( m_trackedDistance, true );
		}
		else
		{
			inkTextRef.SetVisible( m_defaultDistance, false );
			inkTextRef.SetVisible( m_trackedDistance, false );
		}
	}

	private function UpdateFixerData()
	{
		var fixerIcon : UIIcon_Record;
		if( m_data.m_questType == QuestListItemType.Gig || m_data.m_questType == QuestListItemType.Cyberpsycho )
		{
			fixerIcon = TweakDBInterface.GetUIIconRecord( QuestLogUtils.GetFixerData( m_data.m_journalManager, m_data.GetFirstObjective() ) );
			if( fixerIcon.AtlasPartName() != 'None' )
			{
				inkImageRef.SetVisible( m_fixerIcon, true );
				inkImageRef.SetTexturePart( m_fixerIcon, fixerIcon.AtlasPartName() );
				inkImageRef.SetVisible( m_typeIcon, false );
			}
		}
		else
		{
			inkImageRef.SetVisible( m_fixerIcon, false );
			inkImageRef.SetVAlign( m_typeIcon, inkEVerticalAlign.Center );
			inkImageRef.SetVisible( m_typeIcon, true );
		}
	}

	protected event OnSelected( itemController : weak< inkVirtualCompoundItemController >, discreteNav : Bool )
	{
		if( discreteNav )
		{
			SetCursorOverWidget( m_rootWidget );
		}
	}

	protected event OnDeselected( itemController : weak< inkVirtualCompoundItemController > ) {}

	protected event OnToggledOn( itemController : weak< inkVirtualCompoundItemController > )
	{
		var evt : QuestlListItemSelected;
		if( !( m_toggled ) )
		{
			m_toggled = true;
			evt = new QuestlListItemSelected;
			evt.m_questData = m_data.m_questData;
			QueueEvent( evt );
			if( m_hovered )
			{
				PlaySound( 'Button', 'OnPress' );
			}
			UpdateState();
		}
	}

	protected event OnToggledOff( itemController : weak< inkVirtualCompoundItemController > )
	{
		if( m_toggled )
		{
			m_toggled = false;
			UpdateState();
		}
	}

	protected event OnHoverOver( e : inkPointerEvent )
	{
		var target : weak< inkWidget >;
		target = e.GetTarget();
		if( target == m_rootWidget )
		{
			m_hovered = true;
			if( !( m_data.m_isTrackedQuest ) && m_data.m_questType != QuestListItemType.Finished )
			{
				PlayDistanceMarkerAnimation( m_distanceAnim_toHover );
			}
			UpdateState();
		}
	}

	protected event OnHoverOut( e : inkPointerEvent )
	{
		var target : weak< inkWidget >;
		target = e.GetTarget();
		if( target == m_rootWidget )
		{
			m_hovered = false;
			if( !( m_data.m_isTrackedQuest ) && m_data.m_questType != QuestListItemType.Finished )
			{
				PlayDistanceMarkerAnimation( m_distanceAnim_toDefault, true );
			}
			UpdateState();
		}
	}

	protected event OnTrackBtnRelease( e : inkPointerEvent )
	{
		var trackEvt : RequestChangeTrackedObjective;
		if( e.IsAction( 'track' ) || e.IsAction( 'click' ) )
		{
			trackEvt = new RequestChangeTrackedObjective;
			trackEvt.m_quest = m_data.m_questData;
			trackEvt.m_forceSelectEntry = ( ( !( m_toggled ) ) ? ( m_data.GetEntryHash() ) : ( 0 ) );
			QueueEvent( trackEvt );
		}
	}

	protected event OnTrackBtnHoverOver( e : inkPointerEvent )
	{
		if( m_tracked )
		{
			return 0;
		}
		if( m_pinIconAnimProxy )
		{
			m_pinIconAnimProxy.Stop();
			m_pinIconAnimProxy = NULL;
		}
		m_pinIconAnimProxy = PlayLibraryAnimation( m_pinIcon_toHover );
	}

	protected event OnTrackBtnHoverOut( e : inkPointerEvent )
	{
		if( m_tracked )
		{
			return 0;
		}
		if( m_pinIconAnimProxy )
		{
			m_pinIconAnimProxy.Stop();
			m_pinIconAnimProxy = NULL;
		}
		m_pinIconAnimProxy = PlayLibraryAnimation( m_pinIcon_toDefault );
	}

	protected event OnQuestlListItemSelected( e : QuestlListItemSelected )
	{
		if( e.m_questData != m_data.m_questData )
		{
		}
	}

	protected event OnPress( e : inkPointerEvent )
	{
		var trackEvt : RequestChangeTrackedObjective;
		if( ( ( e.IsAction( 'click' ) || e.IsAction( 'track' ) ) && ( e.GetTarget() == m_rootWidget ) ) && m_data.m_questType != QuestListItemType.Finished )
		{
			if( ( m_toggled && !( m_tracked ) ) || e.IsAction( 'track' ) )
			{
				trackEvt = new RequestChangeTrackedObjective;
				trackEvt.m_quest = m_data.m_questData;
				trackEvt.m_forceSelectEntry = ( ( e.IsAction( 'track' ) ) ? ( m_data.GetEntryHash() ) : ( -1 ) );
				QueueEvent( trackEvt );
				e.Consume();
				e.Handle();
			}
		}
	}

	protected event OnUpdateTrackedObjectiveEvent( e : UpdateTrackedObjectiveEvent )
	{
		if( e.m_trackedQuest == m_data.m_questData )
		{
			if( !( m_tracked ) )
			{
				m_tracked = true;
				PlayDistanceMarkerAnimation( m_distanceAnim_toTracked );
				PlayToggleIconAnimation( true );
			}
		}
		else if( m_tracked )
		{
			m_tracked = false;
			PlayDistanceMarkerAnimation( ( ( m_hovered ) ? ( m_distanceAnim_toHover ) : ( m_distanceAnim_toDefault ) ), , true );
			PlayToggleIconAnimation( false );
		}
		UpdateState();
	}

	protected event OnUpdateOpenedQuestEvent( e : UpdateOpenedQuestEvent )
	{
		if( m_openedQuest != e.m_openedQuest )
		{
			m_openedQuest = e.m_openedQuest;
		}
	}

	private function PlayDistanceMarkerAnimation( targetAnimation : CName, optional instant : Bool, optional playReversed : Bool )
	{
		var playbackOptions : inkAnimOptions;
		if( m_distanceMarkerAnimProxy )
		{
			m_distanceMarkerAnimProxy.Stop( true );
			m_distanceMarkerAnimProxy = NULL;
		}
		if( targetAnimation == m_distanceAnim_toHover )
		{
			playbackOptions.executionDelay = m_distanceAnim_toHover_delay;
			playbackOptions.playReversed = playReversed;
		}
		m_distanceMarkerAnimProxy = this.PlayLibraryAnimation( targetAnimation, playbackOptions );
		if( instant )
		{
			m_distanceMarkerAnimProxy.GotoEndAndStop( true );
		}
	}

	private function PlayToggleIconAnimation( show : Bool, optional instant : Bool )
	{
		var playbackOptions : inkAnimOptions;
		if( show )
		{
			if( inkWidgetRef.IsVisible( m_toggleAnimatedIndicator ) )
			{
				if( m_toggleOffAnimProxy && m_toggleOffAnimProxy.IsPlaying() )
				{
					m_toggleOffAnimProxy.Stop( true );
					m_toggleOffAnimProxy = NULL;
				}
				if( ( m_toggleOnAnimProxy && m_toggleOnAnimProxy.IsPlaying() ) && instant )
				{
					m_toggleOnAnimProxy.GotoEndAndStop();
					m_toggleOnAnimProxy = NULL;
					return;
				}
			}
			else
			{
				inkWidgetRef.SetVisible( m_toggleAnimatedIndicator, true );
			}
			if( ( !( m_toggleOnAnimProxy ) || !( m_toggleOnAnimProxy.IsPlaying() ) ) || m_toggleOnAnimProxy.IsFinished() )
			{
				m_toggleOnAnimProxy = this.PlayLibraryAnimation( m_toggleMarkAnimation );
			}
			if( instant )
			{
				m_toggleOnAnimProxy.GotoEndAndStop();
			}
		}
		else
		{
			if( m_toggleOnAnimProxy )
			{
				m_toggleOnAnimProxy.Stop( true );
				m_toggleOnAnimProxy = NULL;
			}
			if( instant )
			{
				if( m_toggleOffAnimProxy )
				{
					m_toggleOffAnimProxy.Stop( true );
					m_toggleOffAnimProxy = NULL;
				}
				inkWidgetRef.SetVisible( m_toggleAnimatedIndicator, false );
			}
			else
			{
				inkWidgetRef.SetVisible( m_toggleAnimatedIndicator, true );
				playbackOptions.playReversed = true;
				m_toggleOffAnimProxy = this.PlayLibraryAnimation( m_toggleMarkAnimation, playbackOptions );
				m_toggleOffAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnHideToggledIconAnimFinished' );
			}
		}
	}

	protected event OnHideToggledIconAnimFinished( proxy : inkAnimProxy )
	{
		inkWidgetRef.SetVisible( m_toggleAnimatedIndicator, false );
	}

	private function UpdateState()
	{
		if( m_toggled )
		{
			m_data.SetVisited();
			inkWidgetRef.SetOpacity( m_questItemFrame, 1.0 );
			inkWidgetRef.SetOpacity( m_questItemBg, ( ( m_hovered ) ? ( 0.04 ) : ( 0.03 ) ) );
		}
		else if( m_hovered )
		{
			inkWidgetRef.SetOpacity( m_questItemFrame, 0.07 );
			inkWidgetRef.SetOpacity( m_questItemBg, 0.03 );
		}
		else if( m_tracked )
		{
			inkWidgetRef.SetOpacity( m_questItemFrame, 0.1 );
			inkWidgetRef.SetOpacity( m_questItemBg, 0.003 );
		}
		else
		{
			inkWidgetRef.SetOpacity( m_questItemFrame, 0.07 );
			inkWidgetRef.SetOpacity( m_questItemBg, 0.003 );
		}
		if( !( m_data.isVisited() ) )
		{
			inkTextRef.SetState( m_title, 'isNew' );
			inkTextRef.SetState( m_description, 'isNew' );
		}
		else
		{
			inkTextRef.SetState( m_title, 'Default' );
			inkTextRef.SetState( m_description, 'Default' );
		}
	}

}

