/*
* FX Editor List Box
* @version 8-28-06
* @author Joseph 'Pcjoe' Florencio
*/
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "vgui_loadtga.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_fxeditormisc.h"
#include "vgui_fxeditorwindow.h"
#include "vgui_fxeditortabbed.h"
#include "vgui_fxeditorlistbox.h"
#include "vgui_fxtoolpanel.h"
#include <VGUI_TextImage.h>

extern CMouseCapture g_MouseCap;

/*
* List Box Input Signal
*/

// Constructor
CHandler_ListBox::CHandler_ListBox(CListBoxItem *pItem, CListBoxMenu *pMenu)
{	m_pItem = pItem;
	m_pMenu = pMenu;
}

// Mouse Release
void CHandler_ListBox::mouseReleased(MouseCode code,Panel* panel)
{	m_pMenu->setSelected(m_pItem);
	m_pMenu->selectCallback(m_pItem);
}

/*
* Listbox Item
*/
// Constructor
CListBoxItem::CListBoxItem(const char *pText, int idx, int x, int y, int wide, int tall, BitmapTGA *pImageBg, BitmapTGA *pImageMo, BitmapTGA *pImageSel)
{	setIndex(idx);
	setImageBg(pImageBg);
	setImageMouseOver(pImageMo);
	setImageSelect(pImageSel);
	setButton(new CFadeImageButton(x, y, wide, tall, getImageBg(), getImageMouseOver(), pText, NULL, 765*2));
	setText(pText);
	setCurrent(false);
}

// Masta was here
// Set as Current
void CListBoxItem::setAsCurrent( void )
{	getButton()->setImage(getImageSelect());
	setCurrent(true);
}

// Disable Current
void CListBoxItem::disableCurrent( void )
{	getButton()->setImage(getImageBg());
	setCurrent(false);
}

/*
* Listbox
*/
#define LIST_BOX_ENTRY_HEIGHT 16

// Constructor
CListBoxMenu::CListBoxMenu(int x, int y, int wide, int tall, const char *imgbg, const char *imgmo, const char *imgsel) : CTFScrollPanel(x,y,wide,tall)
{	if(imgbg)
		setImageBg(getImageVGUIBTGA(imgbg));
	if(imgmo)
		setImageMouseOver(getImageVGUIBTGA(imgmo));
	if(imgsel)
		setImageSelect(getImageVGUIBTGA(imgsel));
	
	setScrollBarAutoVisible(false, false);
	setScrollBarVisible(false, true);
	setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	validate();
}

// Destructor
CListBoxMenu::~CListBoxMenu()
{	for(size_t i = 0; i < m_Items.size(); ++i)
	{	delete m_Items[i];
	}
}

// Get next avail index
int CListBoxMenu::getNextIndex( void )
{	int idx = 1;
	for(size_t i = 0; i < m_Items.size(); ++i)
	{	if(m_Items[i]->getIndex() == idx)
		{	++idx;
			continue;
		}
	}
	return idx;
}

// Add item - leave index as 0 for auto indexing
CListBoxItem *CListBoxMenu::addItem( const char *text, int idx )
{	if(idx == 0)
		idx = getNextIndex();

	// Set correct position
	int iYPos = (int)m_Items.size()*LIST_BOX_ENTRY_HEIGHT;

	// Add item
	CListBoxItem *pItem = new CListBoxItem(text, idx, 0, iYPos, getClientClip()->getWide(), LIST_BOX_ENTRY_HEIGHT, getImageBg(), getImageMouseOver(), getImageSelect());

	// set extra attributes
	pItem->getButton()->setParent(getClient());
	pItem->getButton()->addInputSignal( new CHandler_ListBox(pItem,this) );
	pItem->getButton()->getTextImage()->setColor(Color(0,0,0,0));

	// Validate local scroll box
	validate();

	// add to list
	m_Items.push_back(pItem);
	return pItem;
}

// Set Selected
void CListBoxMenu::setSelected( int idx )
{	disableAllSelect();
	for( size_t i = 0; i < m_Items.size(); ++i )
	{	if(m_Items[i]->getIndex() == idx)
		{	m_Items[i]->setAsCurrent();
		}
	}
}

// Set Selected
void CListBoxMenu::setSelected( string strItem )
{	disableAllSelect();
	for( size_t i = 0; i < m_Items.size(); ++i )
	{	if(m_Items[i]->getText() == strItem)
		{	m_Items[i]->setAsCurrent();
		}
	}
}

// Set Selected
void CListBoxMenu::setSelected( CListBoxItem *pItem )
{	disableAllSelect();
	pItem->setAsCurrent();
}

// Disable all select
void CListBoxMenu::disableAllSelect( void )
{	for( size_t i = 0; i < m_Items.size(); ++i )
	{	m_Items[i]->disableCurrent();
	}
}

// Remove All
void CListBoxMenu::removeAll( void )
{	for( size_t i = 0; i < m_Items.size(); ++i )
	{	// Remove from panel as well
		getClient()->removeChild(m_Items[i]->getButton());
		delete m_Items[i];
	}
	m_Items.clear();

	validate();
}

/*
* Drop Down Menu Input Signal
*/
// Constructor
CHandler_DropDown::CHandler_DropDown(CListBoxDropDownMenu *pMenu)
{	m_pMenu = pMenu;
}

// Mouse Release
void CHandler_DropDown::mouseReleased(MouseCode code,Panel* panel)
{	// Show or hide drop down panel
	if(m_pMenu->isVisible())
	{	m_pMenu->hidePanel();
	}
	else
	{	m_pMenu->showPanel();
	}
}

/*
* List Box Drop Down (used with drop down menu)
*/
// Constructor
CListBoxDropDownMenu::CListBoxDropDownMenu(int x, int y, int wide, int tall, const char *imgbg, const char *imgmo, const char *imgsel) : CListBoxMenu(x, y, wide, tall, imgbg, imgmo, imgsel)
{	setVisible(false);
}

// Select Callback (called whenever an item is clicked on)
void CListBoxDropDownMenu::selectCallback( CListBoxItem *pItem )
{	if(getDropDownMenu())
	{	pItem->getText();
		getDropDownMenu()->updateText(pItem->getText());
		hidePanel();
	}
}

// Show panel
void CListBoxDropDownMenu::showPanel( void )
{	if(!isVisible())
	{	setVisible(true);
		gViewPort->addChild(this);
		// Position correctly
		repositionPanel();
	}
}

// Hide panel
void CListBoxDropDownMenu::hidePanel( void )
{	if(isVisible())
	{	setVisible(false);
		gViewPort->removeChild(this);
	}
}

// Reposition Panel
void CListBoxDropDownMenu::repositionPanel( void )
{	if(getDropDownMenu())
	{	int x = 0;
		int y = getDropDownMenu()->getTall();
		getDropDownMenu()->localToScreen(x,y);
		gViewPort->screenToLocal(x,y);
		setPos(x,y);
	}
}

/*
* Drop Down Menu
*/
// Constructor
CDropDownMenu::CDropDownMenu(int x, int y, int wide, int tall) : CTransparentPanel(222, x, y, wide, tall)
{	setMenu( new CListBoxDropDownMenu(0, 0, wide, tall*4, "dropd_btn", "dropd_mo_btn", "dropd_sel_btn") );
	setTextButton( new CFadeImageButton(0, 0, 0, 0, getImageVGUIBTGA("dropd_btn"), getImageVGUIBTGA("dropd_mo_btn"),"") );
	setDownButton( new CFadeImageButton(0, 0, 0, 0, getImageVGUIBTGA("dropd_down_btn"), getImageVGUIBTGA("dropd_down_mo_btn")) );

	// Reposition
	getDownButton()->setPos(wide-getDownButton()->getWide(), 0);
	getTextButton()->setSize(wide-getDownButton()->getWide(),tall);

	// Set parents and input signals
	getTextButton()->setParent(this);
	getTextButton()->getTextImage()->setColor(Color(0,0,0,0));
	getDownButton()->setParent(this);
	getDownButton()->addInputSignal( new CHandler_DropDown(getMenu()) );
	getMenu()->setDropDownMenu(this);
}

// Update text
void CDropDownMenu::updateText( string text )
{	getTextButton()->getTextImage()->setText(text.c_str());
}

// Hacked paint to act as think to update m_pMenu position
void CDropDownMenu::paint()
{	// Update panel position
	if(m_pMenu->isVisible())
	{	m_pMenu->repositionPanel();
	}
	CTransparentPanel::paint();
}


/*
* File Browser
*/
//  Constructor
CFileListBoxMenu::CFileListBoxMenu(int x, int y, int wide, int tall, const char *dir, const char *imgbg, const char *imgmo, const char *imgsel) : CListBoxMenu(x,y,wide,tall,imgbg,imgmo,imgsel)
{	setBaseDir(dir);
	char szPrint[256];
	sprintf(szPrint, "Dir: %s\n", getBaseDir().c_str());
	ConsolePrint(szPrint);
	buildFileList();
}

// Add file type
void CFileListBoxMenu::addFileType( string strType )
{	m_fileTypes.push_back(strType);
}

// Select Callback (called whenever an item is clicked on)
void CFileListBoxMenu::selectCallback( CListBoxItem *pItem )
{	string strDir;
	// Iterate backwards
	if(pItem->getText() == ".." || pItem->getText() == ".")
	{	size_t find = getBaseDir().find_last_of("\\");
		if(find != string.npos)
		{	strDir = getBaseDir().substr(0,find);
		}
		else
		{	return;
		}
	}
	else
	{	strDir = getBaseDir()+string("\\")+pItem->getText();
	}
	
	char szPrint[256];
	sprintf(szPrint, "Dir: %s\n", strDir.c_str());
	ConsolePrint(szPrint);


	// Check to see if this is a directory
	WIN32_FIND_DATA FindData;
	HANDLE hFind = FindFirstFile(strDir.c_str(), &FindData);
	// Only build a file list if it's a directory
	if(hFind != INVALID_HANDLE_VALUE && (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
	{	setBaseDir(strDir);
		buildFileList();
	}
}

// Clear items and add file list
void CFileListBoxMenu::buildFileList( void )
{	// Clear first
	removeAll();

	WIN32_FIND_DATA FindData;

	// Start getting files
	HANDLE hFind = FindFirstFile((getBaseDir()+"\\*.*").c_str(), &FindData);

	if(hFind != INVALID_HANDLE_VALUE)
	{	// Iterate through results
		do
		{	strlwr(FindData.cFileName);
			string strFileName(FindData.cFileName);
			string strSuffix(strFileName.substr(strFileName.find_last_of(".")+1));

			bool bAdd = false;
			if( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
			{	for( size_t i = 0; i < m_fileTypes.size(); ++i )
				{	if(strSuffix == m_fileTypes[i])
					{	bAdd = true;
						break;
					}
				}
			}
			else
			{	bAdd = true;
			}

			// Good, add item
			if(bAdd)
			{	addItem(strFileName.c_str());
			}
		}while(FindNextFile(hFind, &FindData));
	}

	// Validate panel
	validate();
	setScrollValue(0,0);
}