//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================

#include "filesystem.h"
#include "matsys_controls/picker.h"
#include "tier1/KeyValues.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/Button.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"


using namespace vgui;


//-----------------------------------------------------------------------------
//
// Base asset Picker
//
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Sort by asset name
//-----------------------------------------------------------------------------
static int __cdecl PickerBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
	const char *string1 = item1.kv->GetString("choice");
	const char *string2 = item2.kv->GetString("choice");
	return stricmp( string1, string2 );
}


//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CPicker::CPicker( vgui::Panel *pParent, const char *pColumnHeader, const char *pTextType ) : 
	BaseClass( pParent, "Picker" )
{
	m_pPickerType = pColumnHeader;
	m_pPickerTextType = pTextType;

	// FIXME: Make this an image browser
	m_pPickerBrowser = new vgui::ListPanel( this, "Browser" );
 	m_pPickerBrowser->AddColumnHeader( 0, "choice", m_pPickerType, 52, 0 );
    m_pPickerBrowser->SetSelectIndividualCells( true );
	m_pPickerBrowser->SetEmptyListText( "Nothing to pick" );
 	m_pPickerBrowser->SetDragEnabled( true );
 	m_pPickerBrowser->AddActionSignalTarget( this );
	m_pPickerBrowser->SetSortFunc( 0, PickerBrowserSortFunc );
	m_pPickerBrowser->SetSortColumn( 0 );
						 
	// filter selection
	m_pFilterList = new TextEntry( this, "FilterList" );
	m_pFilterList->AddActionSignalTarget( this );
	m_pFilterList->RequestFocus();

	LoadControlSettingsAndUserConfig( "resource/picker.res" );
}


//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CPicker::~CPicker()
{
}


//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CPicker::OnKeyCodePressed( KeyCode code )
{
	if (( code == KEY_UP ) || ( code == KEY_DOWN ) || ( code == KEY_PAGEUP ) || ( code == KEY_PAGEDOWN ))
	{
		KeyValues *pMsg = new KeyValues("KeyCodePressed", "code", code);
		vgui::ipanel()->SendMessage( m_pPickerBrowser->GetVPanel(), pMsg, GetVPanel());
		pMsg->deleteThis();
	}
	else
	{
		BaseClass::OnKeyCodePressed( code );
	}
}


//-----------------------------------------------------------------------------
// Purpose: refreshes the asset list
//-----------------------------------------------------------------------------
void CPicker::SetStringList( const PickerList_t &list ) 
{
	m_Type = list.m_Type;
	m_pPickerBrowser->RemoveAll();	

	int nCount = list.Count();
	for ( int i = 0; i < nCount; ++i )
	{
		const char *pPickerName = list[i].m_pChoiceString;
		KeyValues *kv = new KeyValues( "node", "choice", pPickerName );
		if ( m_Type == PICKER_CHOICE_STRING )
		{
			kv->SetString( "value", list[i].m_pChoiceValue ); 
		}
		else
		{
			kv->SetPtr( "value", list[i].m_pChoiceValuePtr ); 
		}
		int nItemID = m_pPickerBrowser->AddItem( kv, 0, false, false );

		if ( m_Type == PICKER_CHOICE_STRING )
		{
			KeyValues *pDrag = new KeyValues( "drag", "text", list[i].m_pChoiceValue );
			if ( m_pPickerTextType )
			{
				pDrag->SetString( "texttype", m_pPickerTextType );
			}
			m_pPickerBrowser->SetItemDragData( nItemID, pDrag );
		}
	}
	RefreshChoiceList();
}


//-----------------------------------------------------------------------------
// Purpose: refreshes the choice list
//-----------------------------------------------------------------------------
void CPicker::RefreshChoiceList( ) 
{
	// Check the filter matches
	int nMatchingCount = 0;
	int nTotalCount = 0;
	for ( int nItemID = m_pPickerBrowser->FirstItem(); nItemID != m_pPickerBrowser->InvalidItemID(); nItemID = m_pPickerBrowser->NextItem( nItemID ) )
	{
		KeyValues *kv = m_pPickerBrowser->GetItem( nItemID );
		const char *pPickerName = kv->GetString( "choice" );
		bool bVisible = !m_Filter.Length() || Q_stristr( pPickerName, m_Filter.Get() );
		m_pPickerBrowser->SetItemVisible( nItemID, bVisible );
		if ( bVisible )
		{
			++nMatchingCount;
		}
		++nTotalCount;
	}

	char pColumnTitle[512];
	Q_snprintf( pColumnTitle, sizeof(pColumnTitle), "%s (%d/%d)",
		m_pPickerType, nMatchingCount, nTotalCount );
	m_pPickerBrowser->SetColumnHeaderText( 0, pColumnTitle );

	m_pPickerBrowser->SortList();
	if ( ( m_pPickerBrowser->GetSelectedItemsCount() == 0 ) && ( m_pPickerBrowser->GetItemCount() > 0 ) )
	{
		int nItemID = m_pPickerBrowser->GetItemIDFromRow( 0 );
		m_pPickerBrowser->SetSelectedCell( nItemID, 0 );
	}
}


//-----------------------------------------------------------------------------
// Purpose: refreshes dialog on text changing
//-----------------------------------------------------------------------------
void CPicker::OnTextChanged( )
{
	int nLength = m_pFilterList->GetTextLength();
	m_Filter.SetLength( nLength );
	if ( nLength > 0 )
	{
		m_pFilterList->GetText( m_Filter.GetForModify(), nLength+1 );
	}
	RefreshChoiceList();
}


//-----------------------------------------------------------------------------
// Returns the selected string
//-----------------------------------------------------------------------------
PickerChoiceType_t CPicker::GetSelectionType() const
{
	return m_Type;
}

const char *CPicker::GetSelectedString( ) const
{
	if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
		return NULL;

	if ( m_Type != PICKER_CHOICE_STRING )
		return NULL;

	int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
	KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
	return pItemKeyValues->GetString( "value" );
}

void *CPicker::GetSelectedPtr( ) const
{
	if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
		return NULL;

	if ( m_Type != PICKER_CHOICE_PTR )
		return NULL;

	int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
	KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
	return pItemKeyValues->GetPtr( "value" );
}


//-----------------------------------------------------------------------------
// Returns the index of the selected string
//-----------------------------------------------------------------------------
int CPicker::GetSelectedIndex()
{
	if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
		return -1;

	return m_pPickerBrowser->GetSelectedItem( 0 );
}

	
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CPickerFrame::CPickerFrame( vgui::Panel *pParent, const char *pTitle, const char *pPickerType, const char *pTextType ) : 
	BaseClass( pParent, "PickerFrame" )
{
	m_pContextKeyValues = NULL;
	SetDeleteSelfOnClose( true );
	m_pPicker = new CPicker( this, pPickerType, pTextType );
	m_pPicker->AddActionSignalTarget( this );
	m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
	m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
	SetBlockDragChaining( true );

	LoadControlSettingsAndUserConfig( "resource/pickerframe.res" );

	SetTitle( pTitle, false );
}

CPickerFrame::~CPickerFrame()
{
	CleanUpMessage();
}


//-----------------------------------------------------------------------------
// Deletes the message
//-----------------------------------------------------------------------------
void CPickerFrame::CleanUpMessage()
{
	if ( m_pContextKeyValues )
	{
		m_pContextKeyValues->deleteThis();
		m_pContextKeyValues = NULL;
	}
}


//-----------------------------------------------------------------------------
// Purpose: Activate the dialog
//-----------------------------------------------------------------------------
void CPickerFrame::DoModal( const PickerList_t &list, KeyValues *pContextKeyValues )
{
	CleanUpMessage();
	m_pContextKeyValues = pContextKeyValues;
 	m_pPicker->SetStringList( list );
	BaseClass::DoModal();
}


//-----------------------------------------------------------------------------
// On command
//-----------------------------------------------------------------------------
void CPickerFrame::OnCommand( const char *pCommand )
{
	if ( !Q_stricmp( pCommand, "Open" ) )
	{
		KeyValues *pActionKeys = new KeyValues( "Picked" );
		pActionKeys->SetInt( "choiceIndex", m_pPicker->GetSelectedIndex( ) );

		if ( m_pPicker->GetSelectionType() == PICKER_CHOICE_STRING )
		{
			const char *pPickerName = m_pPicker->GetSelectedString( );
			pActionKeys->SetString( "choice", pPickerName );
		}
		else
		{
			void *pPickerPtr = m_pPicker->GetSelectedPtr( );
			pActionKeys->SetPtr( "choice", pPickerPtr );
		}

		if ( m_pContextKeyValues )
		{
			pActionKeys->AddSubKey( m_pContextKeyValues );
			m_pContextKeyValues = NULL;
		}
		PostActionSignal( pActionKeys );
		CloseModal();
		return;
	}

	if ( !Q_stricmp( pCommand, "Cancel" ) )
	{
		CloseModal();
		return;
	}

	BaseClass::OnCommand( pCommand );
}