#pragma once


#include <adept\guiobject.hpp>
#pragma warning (push)
#include <map>
#include <algorithm>
#include <functional>
#include <vector>
#include <list>
#pragma warning (pop)

class gos_DBCS;


extern __int64	tHUDTime,tHUDTextureTime,tHUDTextTime,tHUDFrameTime,tHUDLineTime,tHUDRectTime;	

extern  bool hsh_initialized;

void my_DrawRect( int x1, int y1, int x2, int y2, DWORD Color );
namespace MechWarrior4
{

	class Vehicle;

inline void LDrawRect (const Stuff::Point3D& loc, int x1, int y1, int x2, int y2, DWORD color )
{ my_DrawRect ((int) (x1+loc.x),(int) (y1+loc.y),(int) (x2+loc.x),(int) (y2+loc.y),color); }
inline void DrawRect (const Stuff::Point3D& loc,Point3D size, DWORD color )
{ my_DrawRect ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color); }

void DrawFrame (int x1,int y1,int x2,int y2,DWORD color);
inline void LDrawFrame (const Stuff::Point3D& loc, int x1, int y1, int x2, int y2, DWORD color )
{ DrawFrame ((int) (x1+loc.x),(int) (y1+loc.y),(int) (x2+loc.x),(int) (y2+loc.y),color); }
inline void DrawFrame (const Stuff::Point3D& loc,const Stuff::Point3D& size, DWORD color )
{ DrawFrame ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color); }

void DrawSpecFrame (int x1,int y1,int x2,int y2,DWORD color);
inline void LDrawSpecFrame (const Stuff::Point3D& loc, int x1, int y1, int x2, int y2, DWORD color )
{ DrawSpecFrame ((int) (x1+loc.x),(int) (y1+loc.y),(int) (x2+loc.x),(int) (y2+loc.y),color); }
inline void DrawSpecFrame (const Stuff::Point3D& loc,const Stuff::Point3D& size, DWORD color )
{ DrawSpecFrame ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color); }

void DrawLine (int x1,int y1,int x2,int y2,DWORD color);
inline void LDrawLine (const Stuff::Point3D& loc, int x1, int y1, int x2, int y2, DWORD color )
{ DrawLine ((int) (x1+loc.x),(int) (y1+loc.y),(int) (x2+loc.x),(int) (y2+loc.y),color); }

inline DWORD MakeColor (DWORD red,DWORD green,DWORD blue,DWORD alpha)
{ return (alpha<<24) + (red<<16) + (green<<8) + (blue); }
inline DWORD BrighterColor (DWORD color)
{ DWORD red,green,blue,alpha;
	red = (color>>16) & 0xff;
	green = (color>>8) & 0xff;
	blue = (color) & 0xff;
	alpha = (color>>24) & 0xff;
	if ((red <<1) > 255)
		red = 255;
	else
		red = red<<1;
	if ((green <<1) > 255)
		green = 255;
	else
		green = green<<1;
	if ((blue <<1) > 255)
		blue = 255;
	else
		blue = blue<<1;
	return (alpha<<24) + ((red)<<16) + (green<<8) + (blue);
}
inline DWORD DarkerColor (DWORD color)
{
	DWORD red,green,blue,alpha;
	red = (color>>16) & 0xff;
	green = (color>>8) & 0xff;
	blue = (color) & 0xff;
	alpha = (color>>24) & 0xff;
	red = (int) (red * 0.75f);
	green = (int) (green * 0.75f);
	blue = (int) (blue * 0.75f);
	return (alpha<<24) + ((red)<<16) + (green<<8) + (blue);
}

	const int MAX_HUD_TEXT = 255;
	struct HUDRectData
	{
		int x1,y1,x2,y2;
		DWORD color;
		HUDRectData (int p1,int p2,int p3,int p4,int p5)
		{
			x1 = p1;
			y1 = p2;
			x2 = p3;
			y2 = p4;
			color = p5;
		}
	};
	inline bool operator< (const HUDRectData& p1,const HUDRectData& p2)
	{
		return (p1.color&0xff000000) < (p2.color&0xff000000);
	}
	extern stlport::vector <HUDRectData> *g_HUDRectRender;

	extern Stuff::Scalar g_AdjustMultX,g_AdjustMultY;
	extern Scalar g_HUDHeatLevel;
	extern Scalar g_HUDPPCLevel;
	void AdjustCoords (int& left, int& top,int& right, int& bottom);
	void AdjustCoords (Scalar& left, Scalar& top,Scalar& right, Scalar& bottom);
	void AdjustCoords (Scalar& left, Scalar& top);
	void AdjustCoords (int& left, int& top);

	class HUDTexture
	{
		
	public:
		enum FLIP {
			NO_FLIP,
			XFLIP,
			YFLIP,
			XYFLIP
		};
		struct RenderData
		{
			Stuff::Point3D loc;
			Stuff::Point3D size;
			DWORD color;
			FLIP flip;
			HUDTexture *texture;

			RenderData (HUDTexture *p1,const Stuff::Point3D& p2,const Stuff::Point3D& p3,DWORD p4,FLIP p5)
			{
				texture = p1;
				loc = p2;
				size = p3;
				color = p4;
				flip = p5;
			}
		};
	protected:
		static stlport::vector <RenderData *> *g_TextureRender;
		static float TOffset;

		MidLevelRenderer::MLRTexture *m_Texture;
		Stuff::Scalar m_TopLeft[2],m_BottomRight[2];			// normalized uv's for texture
		static int m_LastTextureHandle;
		Stuff::Scalar m_Width,m_Height;
		Stuff::Scalar m_Rotation;
		Stuff::Scalar m_CosRot,m_SinRot;
		Stuff::Scalar m_OriginX,m_OriginY;
		Stuff::Scalar m_ScaleX,m_ScaleY;
		int m_BlendMode;
		int m_AlphaMode;

		bool m_Clip;

		void DrawImplementation (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip = NO_FLIP,bool drawnow=false);

	public:
		static void StartTexturePass (void);
		static void EndTexturePass (void);

		HUDTexture (const char *name,Stuff::Scalar left=0,Stuff::Scalar top=0,Stuff::Scalar right=1.0f,Stuff::Scalar bottom=1.0f,Stuff::Scalar width=256.0f,Stuff::Scalar height=256.0f);
		~HUDTexture ();
		void TopLeft (Stuff::Scalar x,Stuff::Scalar y);
		void BottomRight (Stuff::Scalar x,Stuff::Scalar y);
		void Origin (Stuff::Scalar x,Stuff::Scalar y)
		{ m_OriginX = x; m_OriginY = y; }
		void Scale (Stuff::Scalar x,Stuff::Scalar y)
		{ m_ScaleX = x; m_ScaleY = y; }

		int TextureID (void) const;
		void Rotate (Stuff::Scalar value);
		void Clip (bool value)
		{ m_Clip = value; }
		void BlendMode (int value)
		{ m_BlendMode = value; }
		void AlphaMode (int value)
		{ m_AlphaMode = value; }

		Stuff::Scalar Left (void) const
		{ return m_TopLeft[0]; }
		Stuff::Scalar Top (void) const
		{ return m_TopLeft[1]; }
		Stuff::Scalar Right (void) const
		{ return m_BottomRight[0]; }
		Stuff::Scalar Bottom (void) const
		{ return m_BottomRight[1]; }
		MidLevelRenderer::MLRTexture *Texture (void)
		{ return m_Texture; }
		Stuff::Point3D Size (void)
		{
			Stuff::Point3D toret;
			toret.x = (Right () - Left ()) * m_Width;
			toret.y = (Bottom () - Top ()) * m_Height;
			toret.z = 0.0f;
			return toret;
		}

		void Draw (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip = NO_FLIP,bool drawnow=false);
	};

	class ReviewTexture
	{
		
	public:
		enum FLIP {
			NO_FLIP,
			XFLIP,
			YFLIP,
			XYFLIP
		};
	protected:
		DWORD m_TextureHandle;

		Stuff::Scalar m_TopLeft[2],m_BottomRight[2];			// normalized uv's for texture
		Stuff::Scalar m_Width,m_Height;
		Stuff::Scalar m_Rotation;
		Stuff::Scalar m_CosRot,m_SinRot;
		Stuff::Scalar m_OriginX,m_OriginY;
		Stuff::Scalar m_ScaleX,m_ScaleY;
		int m_BlendMode;
		int m_AlphaMode;

		bool m_Clip;

		void DrawImplementation (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip = NO_FLIP);

	public:
		ReviewTexture (const char *name,Stuff::Scalar left=0,Stuff::Scalar top=0,Stuff::Scalar right=1.0f,Stuff::Scalar bottom=1.0f,Stuff::Scalar width=256.0f,Stuff::Scalar height=256.0f,bool alpha = true);
		~ReviewTexture ();
		void TopLeft (Stuff::Scalar x,Stuff::Scalar y);
		void BottomRight (Stuff::Scalar x,Stuff::Scalar y);
		void Origin (Stuff::Scalar x,Stuff::Scalar y)
		{ m_OriginX = x; m_OriginY = y; }
		void Scale (Stuff::Scalar x,Stuff::Scalar y)
		{ m_ScaleX = x; m_ScaleY = y; }

		int TextureID (void) const;
		void Rotate (Stuff::Scalar value);
		void Clip (bool value)
		{ m_Clip = value; }
		void BlendMode (int value)
		{ m_BlendMode = value; }
		void AlphaMode (int value)
		{ m_AlphaMode = value; }

		Stuff::Scalar Left (void) const
		{ return m_TopLeft[0]; }
		Stuff::Scalar Top (void) const
		{ return m_TopLeft[1]; }
		Stuff::Scalar Right (void) const
		{ return m_BottomRight[0]; }
		Stuff::Scalar Bottom (void) const
		{ return m_BottomRight[1]; }
		Stuff::Point3D Size (void)
		{
			Stuff::Point3D toret;
			toret.x = (Right () - Left ()) * m_Width;
			toret.y = (Bottom () - Top ()) * m_Height;
			toret.z = 0.0f;
			return toret;
		}

		void Draw (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip = NO_FLIP);
	};
	inline bool operator< (const HUDTexture::RenderData& p1,const HUDTexture::RenderData& p2)
	{
		return p1.texture->TextureID() < p2.texture->TextureID();
	}

	class HUDText
	{
	protected:
		char m_Text[MAX_HUD_TEXT];
		DWORD m_Color;
    HGOSFONT3D m_Font;
		int m_Justification;
		bool m_Wrap;
		int m_Size;
		gos_DBCS *m_GosObject;

		Stuff::Scalar m_TopLeft[2],m_BottomRight[2];			// margins

		DWORD m_Width,m_Height;
		bool m_BoundsValid;
		bool m_UseOldText;

		static HGOSFONT3D defaultFontHandle;
		static HGOSFONT3D altFontHandle;
		static int defaultFontRefCount;
		static int altFontRefCount;
		static int defaultSmallFontSize,defaultMediumFontSize,defaultLargeFontSize,defaultLarge2FontSize,defaultLarge3FontSize;
		static int deltaSmallSize,deltaMediumSize,deltaLargeSize,deltaLarge2Size,deltaLarge3Size;


	public:
		enum JUSTIFICATION
		{
			LEFT_ALIGN,
			RIGHT_ALIGN,
			CENTER_ALIGN,
			CENTERREGION_ALIGN
		};
		enum
		{
			SMALL_SIZE,
			MEDIUM_SIZE,
			LARGE_SIZE,
			LARGE2_SIZE,
			LARGE3_SIZE
		};

		static void LoadFontSizeDelta (NotationFile *startup_ini);
		HUDText (bool oldtext=false);
		virtual ~HUDText (void);

		void TopLeft (Stuff::Scalar x,Stuff::Scalar y);
		void BottomRight (Stuff::Scalar x,Stuff::Scalar y);

		Stuff::Scalar Left (void) const
		{ return m_TopLeft[0]; }
		Stuff::Scalar Top (void) const
		{ return m_TopLeft[1]; }
		Stuff::Scalar Right (void) const
		{ return m_BottomRight[0]; }
		Stuff::Scalar Bottom (void) const
		{ return m_BottomRight[1]; }
		void Color (DWORD value)
		{ m_Color = value; }
		void Color (DWORD red,DWORD green,DWORD blue,DWORD alpha)
		{ m_Color = MakeColor (red,green,blue,alpha); }
		void Font (HGOSFONT3D value)
		{ m_Font = value; }
		void Justification (JUSTIFICATION value)
		{ m_Justification = value; }
		void Wrap (bool value)
		{ m_Wrap = value; }
		//sanghoon
		void SetAsAlt(){
			m_Font=altFontHandle;
		}
		void SetAsDefault(){
			m_Font=defaultFontHandle;
		}
		virtual void SetSize (int value)
		{
			switch (value)
			{
			case SMALL_SIZE:
				m_Size = defaultSmallFontSize + deltaSmallSize;
				break;
			case MEDIUM_SIZE:
				m_Size = defaultMediumFontSize + deltaMediumSize;
				break;
			case LARGE_SIZE:
				m_Size = defaultLargeFontSize + deltaLargeSize;
				break;
			case LARGE2_SIZE:
				m_Size = defaultLarge2FontSize + deltaLarge2Size;
				break;
			case LARGE3_SIZE:
				m_Size = defaultLarge3FontSize + deltaLarge3Size;
				break;
			default:
				STOP (("bad size for string in hud"));
				break;
			}
#if 0
			if (value)
				m_Size = value-1;				// to correct for some funky math in gos
			else
				m_Size = defaultFontSize-1;				// to correct for some funky math in gos
#endif
		}
		virtual int Size (void) const
		{ return m_Size; }

		virtual void DrawSize (DWORD& x,DWORD& y);

		void UpdateText (const char *text,bool force=false,bool extrareturn=false);
		virtual void Draw (Stuff::Point3D loc, bool bTextSetPos = true);
		virtual void Draw (void);
		virtual void EndPos (DWORD& x,DWORD& y, bool bAdjust = true);
		bool Empty (void)
		{ return (m_Text[0] == 0); }
		//sanghoon begin
		char *hsh_get_m_Text(){return m_Text;}
		//sanghoon end
	};

	class HUDNumberText : public HUDText
	{
	protected:
		static HUDTexture *numTexture;
		static int numTextureRefCount;
		static int HUDNumberText::fontdata[14][11][4];
		
		int GetIndex (int size);

	public:
		HUDNumberText (void);
		virtual ~HUDNumberText (void);
		virtual void DrawSize (DWORD& x,DWORD& y);
		virtual void SetSize (int value)
		{
			switch (value)
			{
			case SMALL_SIZE:
				m_Size = -8;
				break;
			case MEDIUM_SIZE:
				m_Size = -10;
				break;
			case LARGE_SIZE:
				m_Size = defaultLarge2FontSize + deltaLarge2Size;
				break;
			case LARGE2_SIZE:
				case LARGE3_SIZE:
				m_Size = -12;
				break;
			default:
				STOP (("bad size for string in hud"));
				break;
			}
#if 0
			if (value)
				m_Size = value;
			else
				m_Size = defaultFontSize;
#endif
		}
		virtual int Size (void) const
		{ return m_Size; }
		virtual void Draw (void)
		{ STOP (("Should not call HUDNumberText::Draw")); }
		virtual void Draw (Stuff::Point3D loc);

	};

	typedef GUIObject__ClassData        HUDComponent__ClassData;
	typedef GUIObject__Message          HUDComponent__Message;

	class HUDComponent
	{
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Inheritance Support
		//
	public:
		typedef HUDComponent__ClassData     ClassData;
		typedef HUDComponent__Message       Message;

	public:
		static void InitializeClass();
		static void TerminateClass();

		HUDComponent(ClassData *class_data,Stuff::Page *instance_page);

		HUDComponent(ClassData *class_data,Stuff::MemoryStream *stream);
		HUDComponent(ClassData *class_data = DefaultData);

		void Save(Stuff::MemoryStream *stream);

		~HUDComponent();

		void TestInstance();

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Execution support
		//
	public:
		enum ALIGNMENT {
			LEFT_ALIGN,
			CENTER_ALIGNX,
			CENTER_ALIGNY,
			CENTER_ALIGNBOTH,
			RIGHT_ALIGN
		};

	protected:
		bool m_Visible;
		ALIGNMENT m_Alignment;
		mutable Stuff::SlotOf<Vehicle *> m_Vehicle;

		Stuff::Point3D m_Location;			// normalized

		Stuff::Point3D m_Size;					
		Stuff::Time m_LastUpdateTime;

		DWORD m_Color;

		stlport::map <int,HUDTexture *> m_Textures;
		stlport::map <int,ReviewTexture *> m_ReviewTextures;

		virtual void DrawImplementation (void);
		HUDTexture *AddTexture (const char *name,int id,Stuff::Scalar left=0,Stuff::Scalar top=0,Stuff::Scalar right=1.0f,Stuff::Scalar bottom=1.0f,Stuff::Scalar width=256.0f,Stuff::Scalar height=256.0f);
		ReviewTexture *AddReviewTexture (const char *name,int id,Stuff::Scalar left=0,Stuff::Scalar top=0,Stuff::Scalar right=1.0f,Stuff::Scalar bottom=1.0f,Stuff::Scalar width=256.0f,Stuff::Scalar height=256.0f,bool alpha=true);

	public:
		virtual void SetVehicle (Vehicle *veh);
		Vehicle *GetVehicle (void)
		{ return m_Vehicle.GetCurrent (); }
		void Draw(bool vehoverride=false)
		{
			if (!m_Visible)
				return;
			if ((!vehoverride) && (!m_Vehicle.GetCurrent ()))
				return;
			DrawImplementation ();
		}
		virtual void Update (Stuff::Time till)
		{
			m_LastUpdateTime = till;
		}

		virtual void Reset (void)
		{ }

		virtual void Show (void)
		{ m_Visible = true; }
		virtual void Hide (void)
		{ m_Visible = false; }
		bool Visible (void)
		{ return m_Visible; }
		
		void Color (DWORD value)
		{ m_Color = value; }
		void Color (DWORD red,DWORD green,DWORD blue,DWORD alpha)
		{ m_Color = MakeColor (red,green,blue,alpha); }
		DWORD Color (void) const
		{ return m_Color; }
		void Red (DWORD value)
		{ m_Color = (m_Color&0xFF00FFFF) + (value << 16); }
		void Green (DWORD value)
		{ m_Color = (m_Color&0xFFFF00FF) + (value << 8); }
		void Blue (DWORD value)
		{ m_Color = (m_Color&0xFFFFFF00) + (value); }
		void Alpha (DWORD value)
		{ m_Color = (m_Color&0x00FFFFFF) + (value << 24); }
		
		DWORD Red (void) const
		{ return ((m_Color>>16) & 0xff); }
		DWORD Green (void) const
			{ return ((m_Color>>8) & 0xff); }
		DWORD Blue (void) const
			{ return ((m_Color) & 0xff); }
		DWORD Alpha (void) const
			{ return ((m_Color>>24) & 0xff); }

		ALIGNMENT Alignment (void) const
		{ return m_Alignment; }
		void Alignment (ALIGNMENT newalign)
		{ m_Alignment = newalign; }

		void Location (const Stuff::Point3D& newpt)
		{
			m_Location = newpt;
		}
		Stuff::Point3D LocationRaw (void) const
		{ return m_Location; }
		Stuff::Point3D Location (void) const
		{
			Stuff::Point3D toret;
			toret = m_Location;
			if (toret.x <= 1.0f)
				toret.x *= 800;
			if (toret.y <= 1.0f)
				toret.y *= 600;
			return toret;
		}

		void Size (const Stuff::Point3D& newpt)
		{ m_Size = newpt;}
		Stuff::Point3D SizeRaw (void) const
		{ return m_Size; }
		Stuff::Point3D Size (void) const
		{
			Stuff::Point3D toret;
			toret = m_Size;
			if (toret.x <= 1.0f)
				toret.x *= 800;
			if (toret.y <= 1.0f)
				toret.y *= 600;
			return toret;
		}

		Stuff::Point3D TopLeft (void) const;

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Class Data support
		//
	public:
		static ClassData *DefaultData;

	};

}

