/*
* FX Editor Misc Classes
* @version 7-09-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_fxtoolpanel.h"
#include <VGUI_TextImage.h>

extern CMouseCapture g_MouseCap;

// Get Image Pointer
BitmapTGA *getImageVGUIBTGA( string strPath )
{	FileInputStream* fis = NULL;
	// Load both icons
	std::string strImage = "gfx/vgui/640_";
	strImage.append(strPath+".tga");
	// reg image
	return vgui_LoadTGA(strImage.c_str());
}

// Get Image Pointer for bitmap tga's
Image *getImageVGUI( string strPath )
{	FileInputStream* fis = NULL;
	// Load both icons
	std::string strImage = "%d_";
	strImage.append(strPath);
	// reg image
	fis = new FileInputStream( GetVGUITGAName(strImage.c_str()), false);
	Image *pImg = new BitmapTGA(fis,true);
	fis->close();
	return pImg;
}

/*
* Tooltip Manager Class
*/
CTooltipManager gTooltip;

#define MAX_TOOLTIP_WIDTH 256
#define DEFAULT_TOOLTIP_HEIGHT 32
#define TIME_TOOLTIP_POPUP 0.25  // How long it takes the tooltip to "expand" to full size once displayed
#define TIME_TOOLTIP_ACTIVATE 0.75 // Time for a tooltip to intially pop show
#define OFFSET_TOOLTIP 4 // Offset on X and Y from the mouse, so we're not touching the tooltip
#define TOOLTIP_EXTRA_BORDER 4 // Extra border so letters such as 'p' wont push outside of the box

// Constructor
CTooltipManager::CTooltipManager( void )
{	setTextImage( new TextImage("") );
	setTipTime(0);
	setTall(0);
	setWide(0);
	setPanel(NULL);
	getTextImage()->setSize(MAX_TOOLTIP_WIDTH, DEFAULT_TOOLTIP_HEIGHT);
}

// Paint tooltip (only paint if needed)
void CTooltipManager::doPaint(vgui::Panel *panel)
{	if(!isEnabled() || !getPanel())
		return;
	
	// Get mouse position
	int x,y;
	App::getInstance()->getCursorPos(x,y);
	panel->screenToLocal(x,y);

	// Compute size delta, account for TIME_TOOLTIP_ACTIVATE delay
	float flSizeDelta=0;
	if(gEngfuncs.GetClientTime()-(getTipTime()+TIME_TOOLTIP_ACTIVATE) > TIME_TOOLTIP_POPUP)
		flSizeDelta = 1.0;
	else
		flSizeDelta = (gEngfuncs.GetClientTime()-(getTipTime()+TIME_TOOLTIP_ACTIVATE))/TIME_TOOLTIP_POPUP;

	// Determine if the tooltip should be displayed to the top left/right, or bottom left/right
	bool bTop=true,bRight=true;
	// Top Right
	if( (x+getWide()+OFFSET_TOOLTIP+TOOLTIP_EXTRA_BORDER) <= ScreenWidth && (y-getTall()-OFFSET_TOOLTIP-TOOLTIP_EXTRA_BORDER) >= 0 )
	{	bTop = true;
		bRight = true;
	}
	// Top Left
	else if( (x-getWide()-OFFSET_TOOLTIP-TOOLTIP_EXTRA_BORDER) >= 0 && (y-getTall()-OFFSET_TOOLTIP-TOOLTIP_EXTRA_BORDER) >= 0 )
	{	bTop = true;
		bRight = false;
	}
	// Bottom Right
	else if( (x+getWide()+OFFSET_TOOLTIP+TOOLTIP_EXTRA_BORDER) <= ScreenWidth && (y+getTall()+OFFSET_TOOLTIP+TOOLTIP_EXTRA_BORDER) <= ScreenHeight )
	{	bTop = false;
		bRight = true;
	}
	// Bottom Left
	else
	{	bTop = false;
		bRight = false;
	}

	// set interpolated size
	int iCompWide = (getWide() * flSizeDelta) + TOOLTIP_EXTRA_BORDER;
	int iCompTall = (getTall() * flSizeDelta) + TOOLTIP_EXTRA_BORDER;

	// Set pos
	if(bTop && bRight)
		getPanel()->setPos(x+OFFSET_TOOLTIP,y-getTall()-OFFSET_TOOLTIP);
	else if(bTop && !bRight)
		getPanel()->setPos(x-iCompWide-OFFSET_TOOLTIP,y-getTall()-OFFSET_TOOLTIP);
	else if(!bTop && bRight)
		getPanel()->setPos(x+OFFSET_TOOLTIP,y+OFFSET_TOOLTIP);
	else
		getPanel()->setPos(x-iCompWide-OFFSET_TOOLTIP,y+OFFSET_TOOLTIP);

	// Set size and pos
	getTextImage()->setPos(0,0);
	getTextImage()->setSize(iCompWide, iCompTall);
	getPanel()->setSize(iCompWide, iCompTall);

	// Draw
	getTextImage()->doPaint(getPanel());
}

// Add tooltip, get text from titles.txt, use strKey to find
void CTooltipManager::addTooltip( string strKey )
{	m_Tooltips[strKey] = CHudTextMessage::BufferedLocaliseTextString( strKey.c_str() );
}

// Enable Tip
void CTooltipManager::enableTip( string strKey )
{	// Find tooltip and set
	map<string,string>::iterator iterFind;
	if((iterFind=m_Tooltips.find(strKey)) != m_Tooltips.end())
	{	setCurrentTip(iterFind->second);
		getTextImage()->setText(getCurrentTip().c_str());
	}
	// set starting time
	setTipTime(gEngfuncs.GetClientTime());

	// Computer proper size of the tooltip
	int compWide, compTall;
	getTextImage()->getTextSize(compWide,compTall);
	// Small tooltip, doesn't need to wrap to a second line.
	if(compWide < MAX_TOOLTIP_WIDTH)
	{	setWide(compWide);
		setTall(compTall);
	}
	// It's a larger one, we need to wrap it
	else
	{	getTextImage()->setSize(MAX_TOOLTIP_WIDTH, DEFAULT_TOOLTIP_HEIGHT);
		getTextImage()->getTextSizeWrapped(compWide,compTall);
		setWide(compWide);
		setTall(compTall);
	}

	// Enable panel
	if(!getPanel())
	{	setPanel(new CTooltipPanel(0,0,1,1));
		getPanel()->setParent(gViewPort);
		getPanel()->setVisible(true);
		getPanel()->setBorder(new LineBorder( Color(255, 0, 0, 0) ));
	}
}

// Disable Tip
void CTooltipManager::disableTip( void )
{	setCurrentTip("");
	getTextImage()->setText("");
	if(getPanel())
	{	gViewPort->removeChild(getPanel());
		setPanel(NULL);
	}
}

// Should/Is a tip currently being displayed?
bool CTooltipManager::isEnabled( void )
{	if(getCurrentTip() != "")
		return true;
	return false;
}

/*
* Tooltip Panel
*/
void CTooltipPanel::paintBackground()
{	// Small delay before tip is drawn
	if(gEngfuncs.GetClientTime()-gTooltip.getTipTime() >= TIME_TOOLTIP_ACTIVATE)
	{	// Draw transparent background
		if(m_iTransparency)
		{	drawSetColor( 0,0,0, m_iTransparency );
			// Take 2 extra units off to account for border
			drawFilledRect(0,0,_size[0]-2,_size[1]-2);
		}
		gTooltip.doPaint(getParent());
	}
}

/*
* Mouse Over Tooltip Enabler
*/
CHandler_TooltipButtonOver::CHandler_TooltipButtonOver( string strTooltip )
{	m_strTooltip = strTooltip;
	gTooltip.addTooltip(strTooltip);
}
	
void CHandler_TooltipButtonOver::cursorEntered(Panel *panel)
{	gTooltip.enableTip(m_strTooltip);
}

void CHandler_TooltipButtonOver::cursorExited(Panel* panel)
{	gTooltip.disableTip();
}
/*
* Image Panel Class
*/
// Constructors
CImagePanel::CImagePanel( string strImage, TILE_DIR tile_dir, int x, int y, int wide, int tall ) : CTransparentPanel( 255, x, y, wide, tall )
{	setImage(getImageVGUI(strImage.c_str()));
	setTile(tile_dir);
	setBounds(x,y,wide,tall);
	setTransparency(0);
}

CImagePanel::CImagePanel( Image *pImage, TILE_DIR tile_dir, int x, int y, int wide, int tall ) : CTransparentPanel( 255, x, y, wide, tall )
{	setImage(pImage);
	setTile(tile_dir);
	setBounds(x,y,wide,tall);
	setTransparency(0);
}

// Paint Background
void CImagePanel::paintBackground()
{	if(_image)
	{	int iImageWide, iImageTall;
		_image->getSize(iImageWide, iImageTall);
		_image->setColor(Color(255,255,255,getTransparency()));
		// Tile
		switch(_tile)
		{
		case PANELTILE_NONE:
			_image->setPos(0,0);
			_image->doPaint(this);
			break;
		case PANELTILE_HORIZONTAL:
			for( int iX = 0; iX < getWide(); iX += iImageWide )
			{	_image->setPos(iX,0);
				_image->doPaint(this);
			}
			break;
		case PANELTILE_VERTICAL:
			for( int iY = 0; iY < getTall(); iY += iImageTall )
			{	_image->setPos(0,iY);
				_image->doPaint(this);
			}
			break;
		case PANELTILE_ALL:
			for( int iX = 0; iX < getWide(); iX += iImageWide )
			{	for( int iY = 0; iY < getTall(); iY += iImageTall )
				{	_image->setPos(iX,iY);
					_image->doPaint(this);
				}
			}
			break;
		}
	}

	// Redraw border
	if(_border)
	{	_border->doPaint(this);
	}
}

/*
* Image Button Class, fades in mouse over
*/
// Constructor
CFadeImageButton::CFadeImageButton( int x,int y,int wide,int tall, BitmapTGA *image, BitmapTGA *image_mo, const char *text, BitmapTGA *image_click, float faderate ) : Button( "", x, y, wide, tall  )
{	// Images
	m_pImage = image;
	m_pImageArmed = image_mo;
	m_pImageClick = image_click;
	// text image
	int twide,ttall;
	if(text)
	{	m_pText = new TextImage(text);
		m_pText->getTextSize(twide,ttall);
		m_pText->setSize(twide,ttall);
	}
	else
		m_pText = NULL;
	// If wide and tall are NULL, compute the size automatically
	if(wide == 0 && tall == 0 && m_pImage)
	{	int compWide,compTall;
		m_pImage->getSize(compWide,compTall);
		setSize(compWide,compTall);
	}
	// add input signal for mouse overing
	addInputSignal(new CHandler_ButtonHighlight(this));
	// set fade times
	setFadeRate(faderate);
	setFading(true);
	setSelected(false);
	setAlpha(255);
}

// Resize Width to Text (padding is x2, applied to left and right)
void CFadeImageButton::resizeWidthToText( int iPadding )
{	if(m_pText)
	{	int wideText,tallText;
		int wideBtn,tallBtn;
		m_pText->getTextSize(wideText,tallText);
		getSize(wideBtn,tallBtn);

		// add padding to text
		wideText += iPadding * 2;

		// set new wide size
		setSize(wideText,tallBtn);
	}
}

// Paint Background
void CFadeImageButton::paintBackground()
{	// No bg
}

// Paint
void CFadeImageButton::paint()
{	// Set fading status (fade = true fades OUT (nothing by default), fade = false fades IN)
	if(isArmed() == isFading())
		setFading(!isFading());

	// Fade accordingly
	if(isFading())
	{	if(getAlpha() < 255)
		{	setAlpha(getAlpha()+getFadeRate()*gHUD.m_flTimeDelta);
			if(getAlpha() > 255)
				setAlpha(255);
		}
	}
	else
	{	if(getAlpha() > 0)
		{	setAlpha(getAlpha()-getFadeRate()*gHUD.m_flTimeDelta);
			if(getAlpha() < 0)
				setAlpha(0);
		}
	}

	// Draw regular images if we don't have our mouse held down
	if(m_pImageClick && (isSelected() || g_MouseCap.getStatus(0)))
	{	m_pImageClick->setPos(0,0);
		m_pImageClick->doPaint(this);
	}
	else
	{	// Always draw the original image
		m_pImage->setPos(0,0);
		m_pImage->doPaint(this);
		
		// Draw mouseover
		if(getAlpha() != 255)
		{	// Draw mouse over
			m_pImageArmed->setColor(Color(255, 255, 255, getAlpha()));
			m_pImageArmed->setPos(0,0);
			m_pImageArmed->doPaint(this);
		}
	}

	// Render text if we have any
	if(m_pText)
	{	// Center
		int wide,tall;
		getSize(wide,tall);
		int textWide,textTall;
		m_pText->getTextSize(textWide,textTall);
		int xCenter = wide/2 - textWide/2;
		int yCenter = tall/2 - textTall/2;
		// Paint
		m_pText->setPos(xCenter,yCenter);
		m_pText->doPaint(this);
	}
	
	// Redraw border if we have one
	if(_border)
	{	_border->doPaint(this);
	}
}