class CodexListVirtualEntry extends inkVirtualCompoundItemController
{
	protected editable var m_title : inkTextRef;
	protected editable var m_icon : inkImageRef;
	protected editable var m_newWrapper : inkWidgetRef;
	protected editable var m_ep1Icon : inkWidgetRef;
	private var m_entryData : CodexEntryData;
	private var m_nestedListData : VirutalNestedListData;
	private var m_activeItemSync : weak< CodexListSyncData >;
	private var m_isActive : Bool;
	private var m_isItemHovered : Bool;
	private var m_isItemToggled : Bool;

	protected event OnInitialize()
	{
		RegisterToCallback( 'OnToggledOn', this, 'OnToggledOn' );
		RegisterToCallback( 'OnToggledOff', this, 'OnToggledOff' );
		RegisterToCallback( 'OnSelected', this, 'OnSelected' );
		RegisterToCallback( 'OnDeselected', this, 'OnDeselected' );
	}

	public export function OnDataChanged( value : Variant )
	{
		m_nestedListData = ( ( VirutalNestedListData )( ( ( IScriptable )value ) ) );
		m_entryData = ( ( CodexEntryData )( m_nestedListData.m_data ) );
		m_activeItemSync = m_entryData.m_activeDataSync;
		inkTextRef.SetText( m_title, m_entryData.m_title );
		if( m_entryData.m_isEp1 )
		{
			inkWidgetRef.SetVisible( m_ep1Icon, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_ep1Icon, false );
		}
		CheckIsNew();
		UpdateState();
	}

	protected event OnContactSyncData( evt : CodexSyncBackEvent )
	{
		UpdateState();
	}

	private function CheckIsNew()
	{
		if( m_entryData.m_newEntries.Contains( ( ( Int32 )( m_entryData.m_hash ) ) ) )
		{
			inkWidgetRef.SetVisible( m_newWrapper, true );
			inkWidgetRef.SetState( m_newWrapper, 'isNew' );
			inkTextRef.SetState( m_title, 'isNew' );
			inkImageRef.SetState( m_icon, 'isNew' );
		}
		else
		{
			inkWidgetRef.SetVisible( m_newWrapper, false );
			inkWidgetRef.SetState( m_newWrapper, 'Default' );
			inkTextRef.SetState( m_title, 'Default' );
			inkImageRef.SetState( m_icon, 'Default' );
		}
	}

	protected event OnEntrySelected( evt : CodexEntrySelectedEvent )
	{
		if( m_entryData.m_newEntries.Contains( ( ( Int32 )( evt.m_hash ) ) ) )
		{
			m_entryData.m_newEntries.Remove( ( ( Int32 )( evt.m_hash ) ) );
		}
		CheckIsNew();
	}

	protected event OnToggledOn( itemController : weak< inkVirtualCompoundItemController > )
	{
		var evt : CodexSelectedEvent;
		evt = new CodexSelectedEvent;
		evt.m_entryHash = m_entryData.m_hash;
		evt.m_level = m_nestedListData.m_level;
		evt.m_group = m_nestedListData.m_isHeader;
		evt.m_data = m_entryData;
		QueueEvent( evt );
		m_isItemToggled = true;
	}

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

	protected event OnSelected( itemController : weak< inkVirtualCompoundItemController >, discreteNav : Bool )
	{
		m_isItemHovered = true;
		UpdateState();
		if( discreteNav )
		{
			SetCursorOverWidget( GetRootWidget() );
		}
	}

	protected event OnDeselected( itemController : weak< inkVirtualCompoundItemController > )
	{
		m_isItemHovered = false;
		UpdateState();
	}

	private function UpdateState()
	{
		if( ( m_activeItemSync.m_level == m_nestedListData.m_level ) && m_nestedListData.m_isHeader )
		{
			GetRootWidget().SetState( 'SubActive' );
		}
		else if( ( m_activeItemSync.m_entryHash == m_entryData.m_hash ) && !( m_nestedListData.m_isHeader ) )
		{
			GetRootWidget().SetState( 'Active' );
		}
		else if( m_isItemHovered )
		{
			GetRootWidget().SetState( 'Hover' );
		}
		else
		{
			GetRootWidget().SetState( 'Default' );
		}
	}

}

class CodexListVirtualGroup extends inkVirtualCompoundItemController
{
	protected editable var m_title : inkTextRef;
	protected editable var m_arrow : inkWidgetRef;
	protected editable var m_newWrapper : inkWidgetRef;
	protected editable var m_counter : inkTextRef;
	private var m_entryData : CodexEntryData;
	private var m_nestedListData : VirutalNestedListData;
	private var m_activeItemSync : weak< CodexListSyncData >;
	private var m_isActive : Bool;
	private var m_isItemHovered : Bool;
	private var m_isItemToggled : Bool;
	private var m_isItemCollapsed : Bool;

	protected event OnInitialize()
	{
		RegisterToCallback( 'OnToggledOn', this, 'OnToggledOn' );
		RegisterToCallback( 'OnToggledOff', this, 'OnToggledOff' );
		RegisterToCallback( 'OnSelected', this, 'OnSelected' );
		RegisterToCallback( 'OnDeselected', this, 'OnDeselected' );
		inkWidgetRef.SetRotation( m_arrow, 90.0 );
	}

	public export function OnDataChanged( value : Variant )
	{
		m_nestedListData = ( ( VirutalNestedListData )( ( ( IScriptable )value ) ) );
		m_entryData = ( ( CodexEntryData )( m_nestedListData.m_data ) );
		m_activeItemSync = m_entryData.m_activeDataSync;
		inkTextRef.SetText( m_title, m_entryData.m_title );
		inkTextRef.SetText( m_counter, ( "(" + ( ( String )( m_entryData.m_counter ) ) ) + ")" );
		CheckIsNew();
		UpdateState();
	}

	protected event OnContactSyncData( evt : CodexSyncBackEvent )
	{
		UpdateState();
	}

	protected event OnEntrySelected( evt : CodexEntrySelectedEvent )
	{
		if( m_entryData.m_newEntries.Contains( ( ( Int32 )( evt.m_hash ) ) ) )
		{
			m_entryData.m_newEntries.Remove( ( ( Int32 )( evt.m_hash ) ) );
		}
		CheckIsNew();
	}

	protected event OnToggledOn( itemController : weak< inkVirtualCompoundItemController > )
	{
		var evt : CodexSelectedEvent;
		evt = new CodexSelectedEvent;
		evt.m_entryHash = m_entryData.m_hash;
		evt.m_level = m_nestedListData.m_level;
		evt.m_group = m_nestedListData.m_isHeader;
		evt.m_data = m_entryData;
		QueueEvent( evt );
		m_isItemToggled = true;
	}

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

	protected event OnSelected( itemController : weak< inkVirtualCompoundItemController >, discreteNav : Bool )
	{
		m_isItemHovered = true;
		UpdateState();
		if( discreteNav )
		{
			SetCursorOverWidget( GetRootWidget() );
		}
		CheckIsNew();
	}

	protected event OnDeselected( itemController : weak< inkVirtualCompoundItemController > )
	{
		m_isItemHovered = false;
		UpdateState();
	}

	private function CheckIsNew()
	{
		if( m_entryData.m_newEntries.Size() > 0 )
		{
			inkWidgetRef.SetState( m_newWrapper, 'isNew' );
			inkTextRef.SetState( m_title, 'isNew' );
			inkWidgetRef.SetState( m_arrow, 'isNew' );
		}
		else
		{
			inkWidgetRef.SetState( m_newWrapper, 'Default' );
			inkTextRef.SetState( m_title, 'Default' );
			inkWidgetRef.SetState( m_arrow, 'Default' );
		}
	}

	private function UpdateState()
	{
		if( ( m_activeItemSync.m_level == m_nestedListData.m_level ) && m_nestedListData.m_isHeader )
		{
			GetRootWidget().SetState( 'SubActive' );
		}
		else if( ( m_activeItemSync.m_entryHash == m_entryData.m_hash ) && !( m_nestedListData.m_isHeader ) )
		{
			GetRootWidget().SetState( 'Active' );
		}
		else if( m_isItemHovered )
		{
			GetRootWidget().SetState( 'Hover' );
		}
		else
		{
			GetRootWidget().SetState( 'Default' );
		}
		if( m_nestedListData && m_activeItemSync )
		{
			m_isItemCollapsed = !( m_activeItemSync.m_toggledLevels.Contains( m_nestedListData.m_level ) );
		}
		if( inkWidgetRef.IsValid( m_arrow ) )
		{
			inkWidgetRef.SetRotation( m_arrow, ( ( m_isItemCollapsed ) ? ( 90.0 ) : ( 180.0 ) ) );
		}
	}

}

class CodexListVirtualNestedDataView extends VirtualNestedListDataView
{
	var m_currentFilter : CodexCategoryType;

	public function SetFilter( filterType : CodexCategoryType )
	{
		m_currentFilter = filterType;
		Filter();
		EnableSorting();
		Sort();
		DisableSorting();
	}

	protected override function FilterItems( data : VirutalNestedListData ) : Bool
	{
		var entryData : CodexEntryData;
		if( m_currentFilter == CodexCategoryType.All || m_currentFilter == CodexCategoryType.Invalid )
		{
			return true;
		}
		entryData = ( ( CodexEntryData )( data.m_data ) );
		return entryData.m_category == ( ( Int32 )( m_currentFilter ) );
	}

	protected override function SortItems( compareBuilder : CompareBuilder, left : VirutalNestedListData, right : VirutalNestedListData )
	{
		var leftData, rightData : CodexEntryData;
		var leftDataTitle, rightDataTitle : String;
		leftData = ( ( CodexEntryData )( left.m_data ) );
		rightData = ( ( CodexEntryData )( right.m_data ) );
		if( ( ( leftData && rightData ) && left.m_isSortable ) && right.m_isSortable )
		{
			leftDataTitle = GetLocalizedText( leftData.m_title );
			rightDataTitle = GetLocalizedText( rightData.m_title );
			compareBuilder.BoolTrue( leftData.m_isNew, rightData.m_isNew ).StringAsc( leftDataTitle, rightDataTitle );
		}
	}

}

class CodexListVirtualNestedListController extends VirtualNestedListController
{
	private var m_currentDataView : weak< CodexListVirtualNestedDataView >;

	public function SetFilter( filterType : CodexCategoryType )
	{
		m_currentDataView.SetFilter( filterType );
	}

	protected override function GetDataView() : VirtualNestedListDataView
	{
		var view : CodexListVirtualNestedDataView;
		view = new CodexListVirtualNestedDataView;
		m_currentDataView = view;
		return view;
	}

}

