#include "global.h"

vec4f HUD::panelCoords[HUD_NUM_PANELS] =	{
	vec4f(  2.5,  97.5,   80,   80 ),		//	HUD_MESG_PANEL,
	vec4f( 82.5,  97.5, 97.5,   85 ),		//	HUD_KILL_PANEL,
	vec4f(   30,     7, 97.5,  1.0 ),		//	HUD_WEAPON_PANEL,
	vec4f(  2.5,     7,   30,  1.0 ),		//	HUD_ARMOR_PANEL,
	vec4f(  2.5,    75,   80, 10.0 ),		//	HUD_SCORE_PANEL,
};

vec3f HUD::messageColor[NUM_MSG_COLS] = {
	vec3f( 1.0, 1.0, 0.3 ),		//  MSGCOL_SYSTEM_NOTICE, 
	vec3f( 1.0, 0.4, 0.4 ),		//  MSGCOL_SYSTEM_ERROR, 
	vec3f( 1.0, 1.0, 0.3 ),		//  MSGCOL_GAME_EVENT, 
	vec3f( 1.0, 0.3, 1.0 ),		//  MSGCOL_CHAT_MSG,
	vec3f( 1.0, 1.0, 0.7 ),		//  MSGCOL_CHAT_USER,
	vec3f( 0.8, 0.8, 0.8 ),		//  MSGCOL_SCORE_BOARD_TITLE,
	vec3f( 0.5, 1.0, 0.5 ),		//  MSGCOL_SCORE_BOARD_GEN,
	vec3f( 0.9, 1.0, 0.3 ),		//  MSGCOL_SCORE_BOARD_LOCAL,
	vec3f( 0.8, 0.8, 0.8 ),		//  MSGCOL_STATUS_NORMAL,
	vec3f( 0.7, 0.7, 0.7 ),		//  MSGCOL_PANEL_BACKGROUND,
};

void HUD::DrawPanel(vec4f coords, float z)
{
	glBegin(GL_TRIANGLE_STRIP);
		glVertex3f(coords[0],coords[1],z);
		glVertex3f(coords[0],coords[3],z);
		glVertex3f(coords[2],coords[1],z);
		glVertex3f(coords[2],coords[3],z);
	glEnd();
}

void HUD::DrawMessages()
{
	hudFont->setScale(2,3,1);

	// Starting position of first line:
	vec3f pos
		(
			panelCoords[HUD_MESG_PANEL][0]+0.5,
			panelCoords[HUD_MESG_PANEL][3]-0.75,
			0
		);
	float lineAlpha;
	char str[MAX_PATH];
	float lineHeight = hudFont->getHeight();
	float yoffset;

	if (messagePanelAlpha > 0)
	{
		glColor4f(0.7, 0.7, 0.7, messagePanelAlpha*hudPanelBaseAlpha );
		DrawPanel(panelCoords[HUD_MESG_PANEL],0);

		for (int mnum=0; mnum < min(numMessageLines,messages.size()); mnum++)
		{
			if (mnum == 0)								lineAlpha = messageLineScrollAmount;
			else if (mnum == numMessageLines-1)	lineAlpha = 1.0-messageLineScrollAmount;
			else											lineAlpha = 1.0;

			yoffset = (mnum + messageLineScrollAmount) * lineHeight;

			MessageInfo& msg = messages[mnum];
			switch (msg.type)
			{
				case MESG_CHAT:
					glColor( messageColor[MESG_GAME_EVENT], lineAlpha*messagePanelAlpha );
					game.netclient.getPlayerName(msg.fromPlayerIdx,str);
					strcat(str,": ");
					hudFont->printxyz(pos[X],pos[Y]+yoffset,pos[Z],str);
					glColor( messageColor[MESG_CHAT], lineAlpha*messagePanelAlpha );
					hudFont->printxyz(pos[X]+hudFont->getStrWidth(str),pos[Y]+yoffset,pos[Z],msg.msg);
					break;
				default:
					glColor( messageColor[msg.type] , lineAlpha*messagePanelAlpha );
					hudFont->printxyz(pos[X],pos[Y]+yoffset,pos[Z],msg.msg);
					break;
			}
		}
	}
	glColor(messageColor[MESG_SYSTEM_NOTICE],1.0);
	if (m_bEditingTextMessage)
		hudFont->printxyz(pos[X],pos[Y]-lineHeight,pos[Z],"Say: %s",m_sWorkingMessage);
}

void HUD::DrawScore()
{
	glColor(messageColor[MSGCOL_PANEL_BACKGROUND],hudPanelBaseAlpha);
	DrawPanel(panelCoords[HUD_SCORE_PANEL],0);

	float lineHeight = hudFont->getHeight();
	float top = panelCoords[HUD_SCORE_PANEL][1] - 1.5*lineHeight;
	float left = panelCoords[HUD_SCORE_PANEL][0] + 2.5;
	float right = panelCoords[HUD_SCORE_PANEL][2] - 2.5;
	float center = (panelCoords[HUD_SCORE_PANEL][2] + panelCoords[HUD_SCORE_PANEL][0])/2.0;
	const float zlev = 0;


	glColor(messageColor[MSGCOL_SCORE_BOARD_TITLE],1);
	hudFont->printxyzCenter(center,top,zlev,"Current Scores:");
	char str[MAX_PLAYER_NAME];
	top -= 2*lineHeight;
	for (int i=0; i < MAX_PLAYERS; i++)
		if (game.world.tank[i].active)		// *** Don't like to do this
		{
			if (i==LOCAL_PLAYER_IDX)
				glColor(messageColor[MSGCOL_SCORE_BOARD_LOCAL],1);
			else
				glColor(messageColor[MSGCOL_SCORE_BOARD_GEN],1);
			game.netclient.getPlayerName(i,str);
			hudFont->printxyz(left,top,zlev,str);
			hudFont->printxyzRight(right,top,zlev,"%d kills / %d deaths",game.world.tank[i].kills,game.world.tank[i].deaths);
			top -= lineHeight;
		}

}

void HUD::DrawStatus()
{
	glColor(messageColor[MSGCOL_PANEL_BACKGROUND],hudPanelBaseAlpha);
	DrawPanel(panelCoords[HUD_ARMOR_PANEL],0);
	DrawPanel(panelCoords[HUD_WEAPON_PANEL],0);

	hudFont->setScale(3.5,5/hudFont->getBaseHeight(),1);
	{
		// Display armor
		float left = panelCoords[HUD_ARMOR_PANEL][0]+1;
		float bottom = panelCoords[HUD_ARMOR_PANEL][3]+1;
		float zlev = 0;
		glColor(messageColor[MSGCOL_STATUS_NORMAL],1);
		hudFont->printxyz(left,bottom,zlev,"Armor: %d %%",game.world.tank[LOCAL_PLAYER_IDX].armor);
	}

	{
		// Display ammo & current weapon
		float left = panelCoords[HUD_WEAPON_PANEL][0]+1;
		float bottom = panelCoords[HUD_WEAPON_PANEL][3]+1;
		float center = (panelCoords[HUD_WEAPON_PANEL][0]+panelCoords[HUD_WEAPON_PANEL][2])/2.0+10;
		float zlev = 0;
		hudFont->printxyz(left,bottom,zlev,"Weapon: %s","Machine Gun");
		hudFont->printxyz(center,bottom,zlev,"Ammo: %s","Plenty");
	}
}

void HUD::Draw()
{
	glDisable(GL_LIGHTING);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0,100,0,100);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);

	DrawMessages();

	DrawStatus();

	if (input.score)
		DrawScore();

	glDisable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
}

void HUD::AddMessage(hudMesgType type, int playerIdx, char* msg)
{
	MessageInfo newmsg = { type, playerIdx, "" };
	strncpy(newmsg.msg,msg,MAX_PATH);
	messages.push_front(newmsg);
	messagePanelIdle = 0;
	messageLineScrollAmount = 0;

	if (messages.size() > numMessageLines)
		messages.pop_back();
}

void HUD::SetWorld(WorldInformation* world)
{
	myworld = world;
}

void HUD::LoadData()
{}

void HUD::RegisterModels()
{
	messagePanelAlpha = 0;
	m_bEditingTextMessage = false;
	hudFont = new GLFont("Arial",NULL,1000.0); /// the 1000 is to allow rough approximations
}
void HUD::ReleaseModels()
{
	if (hudFont)
	{
		delete hudFont;
		hudFont = NULL;
	}
}

void HUD::update(timet dtime)
{
	messagePanelIdle += dtime;
	if (messageLineScrollAmount < 1.0)
	{
		messageLineScrollAmount += messageLineScrollSpeed*dtime;
		if (messageLineScrollAmount > 1.0)
			messageLineScrollAmount = 1.0;

	}

	//float messagePanelTargetAlpha;
	if ( (messagePanelIdle < messagePanelStaticTimeout+messagePanelFadeTime) || m_bEditingTextMessage)
	{
		if (messagePanelIdle < messagePanelFadeTime)
			messagePanelAlpha = max( messagePanelIdle / messagePanelFadeTime, messagePanelAlpha);
		else if (m_bEditingTextMessage)
			messagePanelAlpha = 1.0;
		else if (messagePanelIdle > messagePanelStaticTimeout)
			messagePanelAlpha = 1.0 - (messagePanelIdle-messagePanelStaticTimeout) / messagePanelFadeTime;
		else
			messagePanelAlpha = 1.0;
	}
	else
		messagePanelAlpha=0.0;

}

void HUD::StartEditingMessage()
{
	if (!m_bEditingTextMessage)		// Clear the message out if we're not already editing
		m_sWorkingMessage[0] = NULL;	
	m_bEditingTextMessage = true;
	messagePanelIdle = 0;
}

#define KEYCODE_BACKSPACE 8
#define KEYCODE_RETURN 13
#define KEYCODE_ESC    27

bool HUD::HandleInput(InputEvent_type e)
{
	if (e.type == IE_KB)
	{
		if (m_bEditingTextMessage)
		{
			int idx;
			switch(e.key)
			{
				case KEYCODE_RETURN:
					if (strlen(m_sWorkingMessage) > 0)
						game.netclient.SendChatMesg(m_sWorkingMessage);
					m_bEditingTextMessage = false;
					break;
				case KEYCODE_ESC:
					m_bEditingTextMessage = false;
					break;
				case KEYCODE_BACKSPACE:
					idx = strlen(m_sWorkingMessage);
					m_sWorkingMessage[ idx-1 ] = NULL;
					break;
				default:
					idx = strlen(m_sWorkingMessage);
					if (idx < MAX_MESG_LEN-1)
					{
						m_sWorkingMessage[ idx   ] = e.key;
						m_sWorkingMessage[ idx+1 ] = NULL;
					}
					break;
			}
			return true;
		}
	}
	return false;
}
