using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;

using Tao.OpenGl;
using Tao.Platform.Windows;
using QCGM;
using QCGM.Net;
using QCGM.Exceptions;
using QCGM.Forms;
using QCGM.Boards;
using QCGM.Geometry;
using QCGM.Graphs2;

using Kevin.Arcball;


namespace QCGM
{
	/// <summary>
	/// Summary description for MainDlg.
	/// </summary>
	/// 

	public class MainDlg : System.Windows.Forms.Form
	{
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.MenuItem menuItem17;
		private System.Windows.Forms.MenuItem menuItem20;
		private System.Windows.Forms.MenuItem menuItem21;
		private System.Windows.Forms.Panel panel1;
		//private System.Windows.Forms.StatusBarPanel statusBarPan7el2;
		private System.Windows.Forms.MenuItem menuItem23;
		private System.Windows.Forms.MenuItem menuFileTop;
		private System.Windows.Forms.MenuItem menuNewGame;
		private System.Windows.Forms.MenuItem menuCloseGame;
		private System.Windows.Forms.MenuItem menuRestoreGame;
		private System.Windows.Forms.MenuItem menuSaveAs;
		private System.Windows.Forms.MenuItem menuExit;
		private System.Windows.Forms.MenuItem menuViewTop;
		private System.Windows.Forms.MenuItem menuPerspective;
		private System.Windows.Forms.MenuItem menuShowConsole;
		private System.Windows.Forms.MenuItem menuHelpTop;
		private System.Windows.Forms.MenuItem menuQHelp;
		private System.Windows.Forms.MenuItem menuAbout;
		//private System.ComponentModel.IContainer components = null;
		private Tao.Platform.Windows.SimpleOpenGlControl oglControl;
		private System.Windows.Forms.MenuItem menuPreferences;
		private System.Windows.Forms.MenuItem menuJoinGame;

		private QcConsole qcConsole;
		private ListenerFrm listenerForm;
		private Settings mySettings;
		private Splash splash;
		private CreateNewGame newGame;
		private Net.Server Server;

		private Winner winnerForm = new Winner("");

		private ArrayList playerList;
		private Net.Client ActiveClient = null;

		private int PlayerTurn = 1;

		private Cursor [] myCursors;
		private Icon [] myIcons;
		private object synchronizer = new object();

		private Mouse MyMouse = new Mouse();
		
		private Arcball myArcball;
		private Matrix4fT Transform = new Matrix4fT();
		private Matrix3fT LastRot = new Matrix3fT();
		private Matrix3fT ThisRot = new Matrix3fT();
		private Point2Di LastPoint = new Point2Di();

		protected Camera MyCamera;
		protected int nextChange = 0;

		// crud for picking
		ArrayList MySelectedObjects = new ArrayList();
		
		public enum GameModes { NoGame, Server, Client, Waiting, GameOver };

		private Random rand;

		private GameModes TheMode;
		private GameModes MyMode
		{
			get
			{
				return TheMode;
			}
			set
			{
				TheMode = value;
				switch(value)
				{
					case GameModes.Client:
						//this.statusBarMain.Panels[1].Icon = myIcons[3];
						this.Text = TITLE_CLIENT;
						break;
					case GameModes.Server:
						this.Text = TITLE_SERVER;
						this.statusBarMain.Panels[1].Icon = myIcons[2];
						this.statusBarMain.Panels[1].Text = "No Timer";
						break;
					case GameModes.NoGame:
						this.Text = TITLE_NORMAL;
						this.statusBarMain.Panels[1].Icon = myIcons[2];
						this.statusBarMain.Panels[1].Text = "No Timer";
						break;
					case GameModes.GameOver:
						this.Text = TITLE_NORMAL;
						this.statusBarMain.Panels[1].Icon = myIcons[2];
						this.statusBarMain.Panels[1].Text = "No Timer";
						break;
					case GameModes.Waiting:
						break;
				}
			}
		}

		private const string TITLE_NORMAL = "Quoridor Classic Game Manager";
		private const string TITLE_SERVER = "Quoridor Classic Game Manager";
		private const string TITLE_CLIENT = "Quoridor Classic Game Manager";

		private System.Windows.Forms.Timer timer1;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.StatusBar statusBarMain;
		private System.Windows.Forms.StatusBarPanel statusBarPanel1;
		private System.Windows.Forms.StatusBarPanel statusBarPanel3;
		private System.Windows.Forms.StatusBarPanel statusBarPanel2;
		private System.Windows.Forms.Timer ConnectTimer;
		
		private void ResetCamera()
		{
			MyCamera = new Camera(.25f, 0.0f, 22.0f, 0.25f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
		}

		public MainDlg()
		{
			InitializeComponent();
			
			qcConsole.Hide();

			this.oglControl.InitializeContexts();

			PostMessageToConsole("Welcome to " + TITLE_NORMAL + ".");

			Server = new Net.Server(new Board2());
			this.Server.EventHandler += new Net.Server.ServerEventHandler(this.Server_OnEvent);

			myCursors = new Cursor[3];
			myCursors[0] = new Cursor(GetType(), "Resources.HandNotGrab.cur");
			myCursors[1] = new Cursor(GetType(), "Resources.HandGrab.cur");
			myCursors[2] = new Cursor(GetType(), "Resources.HandGrab_Invalid.cur");

			myIcons = new Icon[7];
			myIcons[0] = new Icon(GetType(), "Resources.GreenLight2.ico");
			myIcons[1] = new Icon(GetType(), "Resources.RedLight2.ico");
			myIcons[2] = new Icon(GetType(), "Resources.timer3.ico");
			myIcons[3] = new Icon(GetType(), "Resources.timer2.ico");
			myIcons[4] = new Icon(GetType(), "Resources.LittleMan.ico");
			myIcons[5] = new Icon(GetType(), "Resources.WackyPlanet.ico");
			myIcons[6] = new Icon(GetType(), "Resources.LittleMan2.ico");

			rand = new Random(unchecked((int)DateTime.Now.Ticks)); 
			
			mySettings = new Settings(QCGM.Text.SettingsFile);

			this.splash = new Splash();
			if(mySettings.ShowStartupSplash)
			{
				this.splash.Show();
			}
			else
			{
				this.splash.Hide();
			}

			MyCamera = new Camera(5.0f, 5.0f, 12.0f, 5.0f, 5.0f, 0.0f, 0.0f, 1.0f, 0.0f);
			
			//myBoard = new Board2();

			this.timer1.Enabled = true;
			
			Gl.glClearDepth(1.0f);									// Depth Buffer Setup

			Gl.glEnable(Gl.GL_DEPTH_TEST);
			Gl.glDepthFunc(Gl.GL_LESS);
			Gl.glDepthMask(Gl.GL_TRUE);
			Gl.glDepthRange(0, 1);

			//Gl.glEnable(Gl.GL_ALPHA_TEST);
			//Gl.glAlphaFunc(Gl.GL_ALWAYS, 1);

			Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);

			// set up antialiased points and lines
			Gl.glEnable(Gl.GL_LINE_SMOOTH);
			Gl.glHint(Gl.GL_LINE_SMOOTH, Gl.GL_NICEST);
			
			// smooth polygons
			Gl.glHint(Gl.GL_POLYGON_SMOOTH_HINT, Gl.GL_NICEST);
			Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);

			// Blending
			Gl.glEnable(Gl.GL_BLEND);
			Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);

			// Set up Light 1

/*			Light1.Ambient = new float [] { 0.25f, 0.25f, 0.25f, 1.0f };
			Light1.Diffuse = new float [] { 1.0f, 1.0f, 1.0f, 1.0f };
			Light1.Position = new float [] { 5.0f, 5.0f, 8.0f, 1.0f };
			Light1.Specular = new float [] { 1.0f, 1.0f, 1.0f, 1.0f };
			Light1.Initialize();
			Gl.glEnable(Light1.GLLight);*/

			Gl.glEnable(Gl.GL_NORMALIZE);

			myArcball = new Arcball(oglControl.Width, oglControl.Height);
			Transform.LoadIdentity();
			LastRot.LoadIdentity();
			ThisRot.LoadIdentity();

			playerList = new ArrayList();

			this.MyMode = GameModes.NoGame;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );

			this.oglControl.DestroyContexts();

			qcConsole.Dispose();
			this.playerList.Clear();
			this.Server.StopListening();
			this.Server.DisconnectAllUsers();
			this.splash.Dispose();
			this.statusBarPanel1.Dispose();
			this.statusBarPanel2.Dispose();
			this.statusBarMain.Dispose();
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(MainDlg));
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.menuFileTop = new System.Windows.Forms.MenuItem();
			this.menuNewGame = new System.Windows.Forms.MenuItem();
			this.menuJoinGame = new System.Windows.Forms.MenuItem();
			this.menuCloseGame = new System.Windows.Forms.MenuItem();
			this.menuItem9 = new System.Windows.Forms.MenuItem();
			this.menuRestoreGame = new System.Windows.Forms.MenuItem();
			this.menuSaveAs = new System.Windows.Forms.MenuItem();
			this.menuItem20 = new System.Windows.Forms.MenuItem();
			this.menuExit = new System.Windows.Forms.MenuItem();
			this.menuViewTop = new System.Windows.Forms.MenuItem();
			this.menuPerspective = new System.Windows.Forms.MenuItem();
			this.menuItem23 = new System.Windows.Forms.MenuItem();
			this.menuShowConsole = new System.Windows.Forms.MenuItem();
			this.menuItem21 = new System.Windows.Forms.MenuItem();
			this.menuPreferences = new System.Windows.Forms.MenuItem();
			this.menuHelpTop = new System.Windows.Forms.MenuItem();
			this.menuQHelp = new System.Windows.Forms.MenuItem();
			this.menuItem17 = new System.Windows.Forms.MenuItem();
			this.menuAbout = new System.Windows.Forms.MenuItem();
			this.panel1 = new System.Windows.Forms.Panel();
			this.oglControl = new Tao.Platform.Windows.SimpleOpenGlControl();
			this.qcConsole = new QCGM.Forms.QcConsole();
			this.timer1 = new System.Windows.Forms.Timer(this.components);
			this.statusBarMain = new System.Windows.Forms.StatusBar();
			this.statusBarPanel1 = new System.Windows.Forms.StatusBarPanel();
			this.statusBarPanel3 = new System.Windows.Forms.StatusBarPanel();
			this.statusBarPanel2 = new System.Windows.Forms.StatusBarPanel();
			this.ConnectTimer = new System.Windows.Forms.Timer(this.components);
			this.panel1.SuspendLayout();
			((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).BeginInit();
			((System.ComponentModel.ISupportInitialize)(this.statusBarPanel3)).BeginInit();
			((System.ComponentModel.ISupportInitialize)(this.statusBarPanel2)).BeginInit();
			this.SuspendLayout();
			// 
			// mainMenu1
			// 
			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuFileTop,
																					  this.menuViewTop,
																					  this.menuHelpTop});
			// 
			// menuFileTop
			// 
			this.menuFileTop.Index = 0;
			this.menuFileTop.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						this.menuNewGame,
																						this.menuJoinGame,
																						this.menuCloseGame,
																						this.menuItem9,
																						this.menuRestoreGame,
																						this.menuSaveAs,
																						this.menuItem20,
																						this.menuExit});
			this.menuFileTop.Text = "&File";
			this.menuFileTop.Click += new System.EventHandler(this.menuFileTop_Click);
			// 
			// menuNewGame
			// 
			this.menuNewGame.Index = 0;
			this.menuNewGame.Text = "&New Game...";
			this.menuNewGame.Click += new System.EventHandler(this.menuNewGame_Click);
			// 
			// menuJoinGame
			// 
			this.menuJoinGame.Index = 1;
			this.menuJoinGame.Text = "&Join Game...";
			this.menuJoinGame.Click += new System.EventHandler(this.menuJoinGame_Click);
			// 
			// menuCloseGame
			// 
			this.menuCloseGame.Enabled = false;
			this.menuCloseGame.Index = 2;
			this.menuCloseGame.Text = "&Close Game";
			this.menuCloseGame.Click += new System.EventHandler(this.menuCloseGame_Click);
			// 
			// menuItem9
			// 
			this.menuItem9.Index = 3;
			this.menuItem9.Text = "-";
			// 
			// menuRestoreGame
			// 
			this.menuRestoreGame.Enabled = false;
			this.menuRestoreGame.Index = 4;
			this.menuRestoreGame.Text = "&Restore Game...";
			// 
			// menuSaveAs
			// 
			this.menuSaveAs.Enabled = false;
			this.menuSaveAs.Index = 5;
			this.menuSaveAs.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
			this.menuSaveAs.Text = "&Save As...";
			// 
			// menuItem20
			// 
			this.menuItem20.Index = 6;
			this.menuItem20.Text = "-";
			// 
			// menuExit
			// 
			this.menuExit.Index = 7;
			this.menuExit.Text = "E&xit";
			this.menuExit.Click += new System.EventHandler(this.menuExit_Click);
			// 
			// menuViewTop
			// 
			this.menuViewTop.Index = 1;
			this.menuViewTop.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						this.menuPerspective,
																						this.menuItem23,
																						this.menuShowConsole,
																						this.menuItem21,
																						this.menuPreferences});
			this.menuViewTop.Text = "&View";
			// 
			// menuPerspective
			// 
			this.menuPerspective.Checked = true;
			this.menuPerspective.Enabled = false;
			this.menuPerspective.Index = 0;
			this.menuPerspective.RadioCheck = true;
			this.menuPerspective.Text = "Free &Perspective";
			this.menuPerspective.Click += new System.EventHandler(this.menuPerspective_Click);
			// 
			// menuItem23
			// 
			this.menuItem23.Index = 1;
			this.menuItem23.Text = "-";
			// 
			// menuShowConsole
			// 
			this.menuShowConsole.Index = 2;
			this.menuShowConsole.Text = "Show &Console";
			this.menuShowConsole.Click += new System.EventHandler(this.menuShowConsole_Click);
			// 
			// menuItem21
			// 
			this.menuItem21.Index = 3;
			this.menuItem21.Text = "-";
			// 
			// menuPreferences
			// 
			this.menuPreferences.Index = 4;
			this.menuPreferences.Text = "P&references";
			this.menuPreferences.Click += new System.EventHandler(this.Preferences_Click);
			// 
			// menuHelpTop
			// 
			this.menuHelpTop.Index = 2;
			this.menuHelpTop.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						this.menuQHelp,
																						this.menuItem17,
																						this.menuAbout});
			this.menuHelpTop.Text = "&Help";
			// 
			// menuQHelp
			// 
			this.menuQHelp.Index = 0;
			this.menuQHelp.Text = "Quoridor Classic &Help";
			this.menuQHelp.Click += new System.EventHandler(this.menuQHelp_Click);
			// 
			// menuItem17
			// 
			this.menuItem17.Index = 1;
			this.menuItem17.Text = "-";
			// 
			// menuAbout
			// 
			this.menuAbout.Index = 2;
			this.menuAbout.Text = "&About Quoridor Classic Game Manager 2004";
			this.menuAbout.Click += new System.EventHandler(this.menuAbout_Click);
			// 
			// panel1
			// 
			this.panel1.BackColor = System.Drawing.SystemColors.Window;
			this.panel1.Controls.Add(this.oglControl);
			this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.panel1.Location = new System.Drawing.Point(0, 0);
			this.panel1.Name = "panel1";
			this.panel1.Size = new System.Drawing.Size(400, 332);
			this.panel1.TabIndex = 1;
			// 
			// oglControl
			// 
			this.oglControl.AccumBits = ((System.Byte)(0));
			this.oglControl.AutoCheckErrors = false;
			this.oglControl.AutoFinish = false;
			this.oglControl.AutoMakeCurrent = true;
			this.oglControl.AutoSwapBuffers = true;
			this.oglControl.BackColor = System.Drawing.Color.Black;
			this.oglControl.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("oglControl.BackgroundImage")));
			this.oglControl.ColorBits = ((System.Byte)(32));
			this.oglControl.DepthBits = ((System.Byte)(16));
			this.oglControl.Dock = System.Windows.Forms.DockStyle.Fill;
			this.oglControl.Location = new System.Drawing.Point(0, 0);
			this.oglControl.Name = "oglControl";
			this.oglControl.Size = new System.Drawing.Size(400, 332);
			this.oglControl.StencilBits = ((System.Byte)(0));
			this.oglControl.TabIndex = 0;
			this.oglControl.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.oglControl_KeyPress);
			this.oglControl.Resize += new System.EventHandler(this.oglControl_Resize);
			this.oglControl.MouseUp += new System.Windows.Forms.MouseEventHandler(this.oglControl_MouseUp);
			this.oglControl.Paint += new System.Windows.Forms.PaintEventHandler(this.oglControl_Paint);
			this.oglControl.DragOver += new System.Windows.Forms.DragEventHandler(this.oglControl_DragOver);
			this.oglControl.MouseMove += new System.Windows.Forms.MouseEventHandler(this.oglControl_MouseMove);
			this.oglControl.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.oglControl_MouseWheel);
			this.oglControl.MouseLeave += new System.EventHandler(this.oglControl_MouseLeave);
			this.oglControl.MouseDown += new System.Windows.Forms.MouseEventHandler(this.oglControl_MouseDown);
			// 
			// qcConsole
			// 
			this.qcConsole.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.qcConsole.ClientSize = new System.Drawing.Size(424, 345);
			this.qcConsole.Location = new System.Drawing.Point(176, 232);
			this.qcConsole.MinimizeBox = false;
			this.qcConsole.MinimumSize = new System.Drawing.Size(320, 240);
			this.qcConsole.Name = "qcConsole";
			this.qcConsole.Text = "Console";
			this.qcConsole.Visible = false;
			this.qcConsole.EventHandler += new QCGM.Forms.QcConsole.ConsoleEventHandler(this.Console_OnEvent);
			// 
			// timer1
			// 
			this.timer1.Interval = 34;
			this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
			// 
			// statusBarMain
			// 
			this.statusBarMain.Location = new System.Drawing.Point(0, 310);
			this.statusBarMain.Name = "statusBarMain";
			this.statusBarMain.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
																							 this.statusBarPanel1,
																							 this.statusBarPanel3,
																							 this.statusBarPanel2});
			this.statusBarMain.ShowPanels = true;
			this.statusBarMain.Size = new System.Drawing.Size(400, 22);
			this.statusBarMain.TabIndex = 2;
			this.statusBarMain.Text = "Status Bar.";
			this.statusBarMain.PanelClick += new System.Windows.Forms.StatusBarPanelClickEventHandler(this.statusBarMain_PanelClick);
			// 
			// statusBarPanel1
			// 
			this.statusBarPanel1.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;
			this.statusBarPanel1.Icon = ((System.Drawing.Icon)(resources.GetObject("statusBarPanel1.Icon")));
			this.statusBarPanel1.Text = "Ready.";
			this.statusBarPanel1.Width = 230;
			// 
			// statusBarPanel3
			// 
			this.statusBarPanel3.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents;
			this.statusBarPanel3.Icon = ((System.Drawing.Icon)(resources.GetObject("statusBarPanel3.Icon")));
			this.statusBarPanel3.Text = "--";
			this.statusBarPanel3.ToolTipText = "The timer area shows how much time left a player has to move.";
			this.statusBarPanel3.Width = 43;
			// 
			// statusBarPanel2
			// 
			this.statusBarPanel2.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents;
			this.statusBarPanel2.Icon = ((System.Drawing.Icon)(resources.GetObject("statusBarPanel2.Icon")));
			this.statusBarPanel2.Text = "Server Inactive";
			this.statusBarPanel2.ToolTipText = "The networking notification area indicates whether the game is running in server " +
				"or client mode, and whether networking is active or inactive.";
			this.statusBarPanel2.Width = 111;
			// 
			// ConnectTimer
			// 
			this.ConnectTimer.Interval = 500;
			// 
			// MainDlg
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.BackColor = System.Drawing.SystemColors.Control;
			this.ClientSize = new System.Drawing.Size(400, 332);
			this.Controls.Add(this.statusBarMain);
			this.Controls.Add(this.panel1);
			this.ForeColor = System.Drawing.SystemColors.ControlText;
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Menu = this.mainMenu1;
			this.MinimumSize = new System.Drawing.Size(320, 240);
			this.Name = "MainDlg";
			this.Text = "Quoridor Classic Game Manager v.1.0";
			this.Load += new System.EventHandler(this.MainDlg_Load);
			this.Closed += new System.EventHandler(this.MainDlg_Closed);
			this.Activated += new System.EventHandler(this.MainDlg_Activated);
			this.panel1.ResumeLayout(false);
			((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.statusBarPanel3)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.statusBarPanel2)).EndInit();
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.EnableVisualStyles(); // Enables Windows XP look and feel.
			Application.Run(new MainDlg());
		}

		private void oglControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			RenderScene();
		}

		private void RenderScene()
		{
			lock(this.synchronizer)
			{
				Gl.glClearColor(0.6f, 0.7f, 1.0f, 1.0f);
				Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer

				Gl.glLoadIdentity();

				Glu.gluLookAt(MyCamera.Pos.Eye.X, MyCamera.Pos.Eye.Y, MyCamera.Pos.Eye.Z,
					MyCamera.Pos.At.X, MyCamera.Pos.At.Y, MyCamera.Pos.At.Z,
					MyCamera.Pos.Up.X, MyCamera.Pos.Up.Y, MyCamera.Pos.Up.Z);

				float [] M = Transform.ToGLArray;
				Gl.glMultMatrixf(this.Transform.ToGLArray);

				Gl.glTranslatef(-5.0f, -5.0f, 0.0f);

				Gl.glInitNames();	// This clears the OpenGL name stack so we always start with 0 names.
				Geometry.Namestack.al.Clear();

				if(this.MyMode == GameModes.Client || this.MyMode == GameModes.GameOver && ActiveClient != null && ActiveClient.Board != null)
				{
					this.ActiveClient.Board.UpdateNamestack();
					this.ActiveClient.Board.Draw();
				}
				else
				{
					this.Server.Board.UpdateNamestack();
					this.Server.DrawBoard();
				}

				Gl.glFlush();
			}
		}

		private void menuAbout_Click(object sender, System.EventArgs e)
		{
			AboutForm aboutForm = new AboutForm();
			aboutForm.Show();
		}
		
		private void menuExit_Click(object sender, System.EventArgs e)
		{
			DialogResult result = System.Windows.Forms.MessageBox.Show("Thank you for using Quoridor Classic Game Manager. Are you sure you want to exit?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

			if (result == DialogResult.Yes)
			{
				Shutdown();
			}
			else
			{
				// return to application normally.
			}
		}

		private void menuShowConsole_Click(object sender, System.EventArgs e)
		{
			if (qcConsole != null)
			{
				if (qcConsole.Visible == false)
				{
					qcConsole.Show();
				}
				qcConsole.Activate();
			}
		}

		private void menuTopDown_Click(object sender, System.EventArgs e)
		{
			
		}

		private void menuPerspective_Click(object sender, System.EventArgs e)
		{
			
		}

		private void changeViewMode(string mode)
		{
			/*try 
			{
				mySettings.setViewMode(Settings.ViewModes.TopDown);

				if(mode == Settings.ViewModes.TopDown)
				{
					menuTopDown.Checked = true;
					menuPerspective.Checked = false;
					
					// Do OpenGL crud here.
				} 
				else if (mode == Settings.ViewModes.Perspective)
				{
					menuTopDown.Checked = false;
					menuPerspective.Checked = true;
					// Do OpenGL crud here.
				}
			} 
			catch(InvalidViewModeException)
			{
			}*/
		}

		private void Preferences_Click(object sender, System.EventArgs e)
		{
			PreferencesDlg preferences = new PreferencesDlg(this.mySettings);
			preferences.ShowDialog();
		}

		private void menuNewGame_Click(object sender, System.EventArgs e)
		{
			this.newGame = new CreateNewGame(this.mySettings);
			this.newGame.ShowDialog();
			
			if (this.newGame.DialogResult == DialogResult.OK)
			{
				CreateNewGame();
			}
		}

		protected void CreateNewGame()
		{
            NewGameSettings newGameSettings = newGame.GetSettings();

			// Start server.
			Server.Name = newGameSettings.serverName;
			Server.Port = newGameSettings.serverPort;

			try
			{
				Server.DisconnectAllUsers();
				Server.Listen(newGameSettings.timeLimit);
			}
			catch (Exception e)
			{
				HandleException(e);
				CloseGame();
				return;
			}

			MyMode = GameModes.Server;

			// Fix menus.
			this.menuNewGame.Enabled = false;
			this.menuJoinGame.Enabled = false;
			this.menuCloseGame.Enabled = true;

			playerList.Clear();

			listenerForm = new ListenerFrm(120);

			if (newGameSettings.isPlayer1Networked == false)
			{
				//this.statusBarMain.Panels[0].Text = "Connecting Player 1...";
				//this.statusBarMain.Panels[0].Icon = this.myIcons[5];
				
				try
				{
					Net.Client newClient = ConnectNewClient(newGameSettings.namePlayer1, newGameSettings.hostName, newGameSettings.serverPort);
					this.playerList.Add(newClient);
				}
				catch (Exception e)
				{
					HandleException(e);
					CloseGame();
				}
			}

//			for(int i=0; i < 500000; i++);

			if (newGameSettings.isPlayer2Networked == false)
			{
				//this.statusBarMain.Panels[0].Text = "Connecting Player 2...";
				//this.statusBarMain.Panels[0].Icon = this.myIcons[5];

				try
				{
					Net.Client newClient = ConnectNewClient(newGameSettings.namePlayer2, newGameSettings.hostName, newGameSettings.serverPort);
					this.playerList.Add(newClient);
				}
				catch (Exception e)
				{
					HandleException(e);
					CloseGame();
				}
			}

			this.MyMode = GameModes.Server;

			// If there are players that still need to connect, then post the
			// listeneing Form so we can watch them connect, or see errors.
			if (this.playerList.Count != 2)
			{
				DialogResult listenerResult = listenerForm.ShowDialog();

				// Stop the game if the user cancels or a timeout occurs.
				if (listenerResult == DialogResult.Cancel)
				{
					this.MyMode = GameModes.NoGame;
					this.menuNewGame.Enabled = true;
					this.menuJoinGame.Enabled = true;
					this.menuCloseGame.Enabled = false;
					CloseGame();
					return;
				}
			}

			bool fail=false;
			foreach(Client c in this.playerList)
			{
				if(c.Connected == false)
				{
					fail=true;
				}
			}

			if(!fail)
			{
				ResetCamera();
				this.Text = TITLE_SERVER;
				//this.statusBarMain.Panels[0].Text = QCGM.Text.Ready;
				//this.statusBarMain.Panels[0].Icon = myIcons[5];
				//this.MyMode = GameModes.Server;
				//MessageBox.Show("Create game supposedly went ok.");
			}
			else
			{
				CloseGame();
				this.MyMode = GameModes.NoGame;
				this.menuNewGame.Enabled = true;
				this.menuJoinGame.Enabled = true;
				this.menuCloseGame.Enabled = false;
				return;
			}

		}

		private DialogResult HandleException(Exception e)
		{
			if(e is SocketException)
			{
				SocketException se = (SocketException)e;
				return MessageBox.Show(
					"SocketException caught by Application.\r\n\r\n" +
					"Source: " + se.Source + "\r\n\r\n" +
					"Socket error code: " + se.ErrorCode + "\r\n\r\n" +
					"Error code description: " + Client.SocketErrorCodeDescription(se.ErrorCode) + "\r\n\r\n" +
					"Message: " + se.Message,
					"Exception Caught",
					MessageBoxButtons.OK,
					MessageBoxIcon.Error);
			}
			else
			{
				return MessageBox.Show(
					"Exception caught by Application: " + e.GetType() + "\r\n\r\n" +
					"Source: " + e.Source + "\r\n\r\n" +
					"Message: " + e.Message,
					"Exception Caught",
					MessageBoxButtons.OK,
					MessageBoxIcon.Error);
			}
		}

		private Net.Client ConnectNewClient(string name, string server, int port)
		{
			Net.Client c = new Net.Client(name, new Board2());
			c.EventHandler += new Net.Client.ClientEventHandler(this.Client_OnEvent);

			IPHostEntry he = Dns.Resolve(server);
			IPEndPoint ep = new IPEndPoint(he.AddressList[0], port);

			lock(synchronizer)
			{
				c.Connect(ep);

				return c;
			}
		}

		private void menuJoinGame_Click(object sender, System.EventArgs e)
		{
			JoinGame joinGame = new JoinGame(this.mySettings);
			DialogResult result = joinGame.ShowDialog();

			if (result == DialogResult.OK)
			{
				try
				{
					Client newClient = ConnectNewClient(joinGame.PlayerName, joinGame.ServerName, joinGame.Port);

					if(newClient.Connected)
					{
						this.playerList.Add(newClient);

						this.ActiveClient = newClient;

						this.MyMode = GameModes.Waiting;

						this.menuCloseGame.Enabled = true;
						this.menuJoinGame.Enabled = false;
						this.menuNewGame.Enabled = false;

						ResetCamera();
					}
					else
					{
						//CloseGame();
						return;
					}
				}
				/*catch(SocketException ex)
				{
					if(ex.ErrorCode == 11001)
					{
						MessageBox.Show(
							"SocketException caught.\r\n\r\n" +
							"Source: " + se.Source + "\r\n\r\n" +
							"Socket error code: " + se.ErrorCode + "\r\n\r\n" +
							"Error code description: " + Client.SocketErrorCodeDescription(se.ErrorCode) + "\r\n\r\n" +
							"Message: " + se.Message,
							"Exception Caught",
							MessageBoxButtons.OK,
							MessageBoxIcon.Error);
					}
					else
					{
						HandleException(ex);
					}
				}*/
				catch(Exception ex)
				{
					//ActiveClient = null;
					//MyMode = GameModes.NoGame;
					//CloseGame();
					HandleException(ex);
				}
			}
		}


		private void oglControl_Resize(object sender, System.EventArgs e)
		{
			myArcball.SetBounds(oglControl.Width, oglControl.Height);
			
			Gl.glViewport(0, 0, oglControl.Width, oglControl.Height);
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glLoadIdentity();

			// Set the correct perspective.
			Glu.gluPerspective(45, (float)oglControl.Width/ (float)(oglControl.Height > 0 ? oglControl.Height : 1), 0.1, 120);
	
			Gl.glMatrixMode(Gl.GL_MODELVIEW);
			Gl.glLoadIdentity();

		}

		private void Server_OnEvent(object sender, ServerEventArgs e)
		{
			lock(synchronizer)
			{
				if (e.stateObject is Net.Messages.Start)
				{
					this.menuCloseGame.Enabled = true;
					this.menuJoinGame.Enabled = false;
					this.menuNewGame.Enabled = false;
				}
				else if (e.stateObject is Net.Messages.Stop)
				{
					this.menuCloseGame.Enabled = false;
					this.menuJoinGame.Enabled = true;
					this.menuNewGame.Enabled = true;
				}
				else if (e.stateObject is Net.Messages.Winner)
				{
					Net.Messages.Winner win = (Net.Messages.Winner)e.stateObject;

					winnerForm.SetText(win.Name);
					this.MyMode = GameModes.GameOver;

					this.statusBarMain.Panels[0].Text = "Winner: " + win.Name;
					this.statusBarMain.Panels[0].Icon = null;

					/*if(winnerForm.Visible == false)
					{
						winnerForm.ShowDialog();
					}*/
				}
				else if (e.stateObject is Net.Messages.WhoseTurn)
				{
					Net.Messages.WhoseTurn msg = (Net.Messages.WhoseTurn)e.stateObject;

					this.PlayerTurn = msg.Turn;

					if(this.MyMode != GameModes.GameOver)
					{
						this.statusBarMain.Panels[0].Text = msg.Name + "'s turn.";
						this.statusBarMain.Panels[0].Icon = myIcons[(msg.Turn==1?4:6)];
					}
					
					foreach(Client c in this.playerList)
					{
						if(c.PlayerNumber == msg.Turn)
						{
							this.ActiveClient = c;
							c.MoveState = Client.MoveStates.ChooseStart;
							if(this.MyMode != GameModes.GameOver)
							{
								this.MyMode = GameModes.Client;
							}
						}
						else
						{
							c.MoveState = Client.MoveStates.Complete;
						}
					}
				}
				else if (e.stateObject is Net.Messages.Timer)
				{
					Net.Messages.Timer t = (Net.Messages.Timer)e.stateObject;

					if(t.TimeRemaining >= 0)
					{
						int h;
						int m;
						int s;

						h = (t.TimeRemaining / 3600) % 24;
						m = (t.TimeRemaining / 60) % 60;
						s = t.TimeRemaining % 60;
						string txt = String.Format("{0:00}:{1:00}:{2:00}", h, m, s);

						if(this.statusBarMain.Panels[1].Icon != myIcons[3])
                            this.statusBarMain.Panels[1].Icon = myIcons[3];
						if(this.statusBarMain.Panels[1].Text != txt)
							this.statusBarMain.Panels[1].Text = txt;
					}
					else
					{
						if(this.statusBarMain.Panels[1].Text != "No Timer")
							this.statusBarMain.Panels[1].Text = "No Timer";
						if(this.statusBarMain.Panels[1].Icon != myIcons[2])
							this.statusBarMain.Panels[1].Icon = myIcons[2];
					}
				}
				else if (e.stateObject is Net.Messages.RightPanel)
				{
					Net.Messages.RightPanel msg = (Net.Messages.RightPanel)e.stateObject;

					this.statusBarMain.Panels[2].Text = msg.Text;

					if (myIcons[0] != null && myIcons[1] != null)
					{
						if (msg.Text == QCGM.Text.Online)
						{
							//try
						{
							this.statusBarMain.Panels[2].Icon = myIcons[0];
						} 
							//catch (Exception ex)
						{
						}
						}
						else if (msg.Text == QCGM.Text.Offline)
						{
							//try
						{
							this.statusBarMain.Panels[2].Icon = myIcons[1];
						}
							//catch (Exception ex)
						{
						}
						}
					}
				}
				else if (e.stateObject is Net.Messages.MiddlePanel)
				{
					Net.Messages.LeftPanel msg = (Net.Messages.LeftPanel)e.stateObject;
					this.statusBarMain.Panels[1].Text = msg.Text;
				}
				else if (e.stateObject is Net.Messages.LeftPanel)
				{
					Net.Messages.LeftPanel msg = (Net.Messages.LeftPanel)e.stateObject;
					this.statusBarMain.Panels[0].Text = msg.Text;
					this.statusBarMain.Panels[0].Icon = this.myIcons[5];
				}
				else if (e.stateObject is Net.Messages.Say)
				{
					Net.Messages.Say msg = (Net.Messages.Say)e.stateObject;
					PostMessageToConsole("Server: " + msg.Text);
				}
					/*else if (e.stateObject is Net.Messages.Turn)
					{
						Net.Messages.Turn msg = (Net.Messages.Turn)e.stateObject;

						//QcClient c = (QcClient)playerList[msg.WhoseTurn];
						statusBarMain.Panels[0].Text = "It is player " + msg.WhoseTurn + "'s turn.";
					}*/
				else if (e.stateObject is Net.Messages.UserLoggedOn)
				{
					Net.Messages.UserLoggedOn msg = (Net.Messages.UserLoggedOn)e.stateObject;
					
					//this.statusBarMain.Panels[0].Text = msg.User.name + " connected OK.";
					//this.statusBarMain.Panels[0].Icon = myIcons[4];

					if (this.listenerForm != null)
					{
						this.listenerForm.Login(msg.User);
					}
				}
				else
				{
					PostMessageToConsole("Unknown Message:" + e.stateObject.ToString());
				}
			}
		}

		private void Client_OnEvent(object sender, ClientEventArgs e)
		{
			lock(synchronizer)
			{
				Net.Client c = (Net.Client)sender;

				if (e.stateObject is Net.Messages.Say)
				{
					Net.Messages.Say msg = (Net.Messages.Say)e.stateObject;
					PostMessageToConsole(c.Name + ": " + msg.Text);
				}
				else if (e.stateObject is Net.Messages.Timer)
				{
					Net.Messages.Timer t = (Net.Messages.Timer)e.stateObject;

					if(t.TimeRemaining >= 0)
					{
						int h;
						int m;
						int s;

						h = (t.TimeRemaining / 3600) % 24;
						m = (t.TimeRemaining / 60) % 60;
						s = t.TimeRemaining % 60;
						string txt = String.Format("{0:00}:{1:00}:{2:00}", h, m, s);

						if(this.statusBarMain.Panels[1].Icon != myIcons[3])
							this.statusBarMain.Panels[1].Icon = myIcons[3];
						if(this.statusBarMain.Panels[1].Text != txt)
							this.statusBarMain.Panels[1].Text = txt;
					}
					else
					{
						if(this.statusBarMain.Panels[1].Text != "No Timer")
							this.statusBarMain.Panels[1].Text = "No Timer";
						if(this.statusBarMain.Panels[1].Icon != myIcons[2])
							this.statusBarMain.Panels[1].Icon = myIcons[2];
					}
				}
				else if (e.stateObject is Net.Messages.WhoseTurn)
				{
					Net.Messages.WhoseTurn msg = (Net.Messages.WhoseTurn)e.stateObject;

					this.PlayerTurn = msg.Turn;
					if(this.MyMode != GameModes.GameOver)
					{
						this.statusBarMain.Panels[0].Text = msg.Name + "'s turn.";
						this.statusBarMain.Panels[0].Icon = myIcons[(msg.Turn==1?4:6)];
					}

					foreach(Client client in this.playerList)
					{
						if(client.PlayerNumber == msg.Turn)
						{
							this.ActiveClient = client;
							client.MoveState = Client.MoveStates.ChooseStart;
							if(this.MyMode != GameModes.GameOver)
							{
								this.MyMode = GameModes.Client;
							}
						}
						else
						{
							client.MoveState = Client.MoveStates.Complete;
							//ActiveClient = null;
						}
					}
				}
				else if (e.stateObject is Net.Messages.Winner)
				{
					Net.Messages.Winner win = (Net.Messages.Winner)e.stateObject;

					winnerForm.SetText(win.Name);
					this.MyMode = GameModes.GameOver;

					this.statusBarMain.Panels[0].Text = "Winner: " + win.Name;
					this.statusBarMain.Panels[0].Icon = null;

					/*if(winnerForm.Visible == false)
					{
						winnerForm.ShowDialog();
					}*/
				}
				else if (e.stateObject is Net.Messages.Say)
				{
					Net.Messages.Say msg = (Net.Messages.Say)e.stateObject;
					
					PostMessageToConsole(msg.Text);
				}
				else
				{
					PostMessageToConsole("Unknown command recieved: " + e.stateObject);
				}
			}
		}

		public void PostMessageToConsole(string message)
		{
			System.Random rnd = new Random();

			lock(synchronizer)
			{
				qcConsole.WriteLine(message);
			}
		}

		private void menuCloseGame_Click(object sender, System.EventArgs e)
		{
			DialogResult result = System.Windows.Forms.MessageBox.Show("This will cause the current game to be reset. You will lose any unsaved moves. Are you sure you want to proceed?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

			if (result == DialogResult.Yes)
			{
				CloseGame();
			}
			else
			{
				// return without doing anything
			}
		}

		private void CloseGame()
		{
			try
			{
				foreach(Client c in playerList)
				{
					c.SendMessage("bye");
				}

				this.MyMode = GameModes.NoGame;
				this.Server.Board.ResetBoard();
				this.Server.DisconnectAllUsers();
				this.Server.StopListening();

				this.playerList.Clear();
				this.menuNewGame.Enabled = true;
				this.menuJoinGame.Enabled = true;
				this.menuCloseGame.Enabled = false;
				this.Text = TITLE_NORMAL;
			}
			catch(Exception)
			{
			}
			finally
			{
				this.statusBarMain.Panels[0].Text = QCGM.Text.Ready;
				this.statusBarMain.Panels[0].Icon = myIcons[5];
			}
		}

		private void statusBarMain_PanelClick(object sender, System.Windows.Forms.StatusBarPanelClickEventArgs e)
		{
		
		}

		private void menuFileTop_Click(object sender, System.EventArgs e)
		{
		
		}

		private void MainDlg_Load(object sender, System.EventArgs e)
		{
			this.Cursor = Cursors.Default;
		}

		private void MainDlg_Closed(object sender, System.EventArgs e)
		{
			Shutdown();
		}

		private void Shutdown()
		{
			lock(synchronizer)
			{
				this.Server.DisconnectAllUsers();
				this.Server.StopListening();
				this.qcConsole.Close();
				this.Close();
				this.mySettings.SaveAs(QCGM.Text.SettingsFile);
			}
			System.Environment.Exit(0);
		}

		private void oglControl_MouseLeave(object sender, System.EventArgs e)
		{
			if(this.MyMode == GameModes.Client && ActiveClient != null)
			{
				ActiveClient.ReleaseObject();
			}
		}

		private void MainDlg_Activated(object sender, System.EventArgs e)
		{
			if (this.splash.Visible == true)
			{
				this.splash.Close();
			}
		}

		private void oglControl_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
		{
			this.Cursor = Cursors.No;
		}


		private void MouseHover_Client(int x, int y)
		{
			if(this.MyMode == GameModes.Client && ActiveClient != null && ActiveClient.PlayerNumber == this.PlayerTurn)
			{
				switch(ActiveClient.Handle_MouseHover(x, y, this.MySelectedObjects))
				{
					case Client.HoverState.Nothing:
						this.Cursor = Cursors.Default;
						break;
					case Client.HoverState.Invalid:
						this.Cursor = Cursors.No;
						break;
					case Client.HoverState.OK:
						this.Cursor = Cursors.Hand;
						break;
					default:
						this.Cursor = Cursors.Default;
						break;
				}
			}
		}

		private void MouseDrag_Client(int x, int y)
		{
			if(this.MyMode == GameModes.Client && ActiveClient != null && ActiveClient.PlayerNumber == this.PlayerTurn)
			{
				switch(ActiveClient.Handle_MouseDrag(x, y, this.MySelectedObjects))
				{
					case Client.DragState.Invalid:
						if(ActiveClient.PickedObject is Wall)
						{
							Wall w = (Wall)ActiveClient.PickedObject;
							w.Color = Geometry.Colors.Red;
							w.Color.Alpha = 0.3f;
						}
						this.Cursor = Cursors.No;
						break;
					case Client.DragState.CanJump:
						this.Cursor = Cursors.Default;
						break;
					case Client.DragState.CanMove:
						this.Cursor = Cursors.Default;
						break;
					case Client.DragState.CanPlaceWall:
						this.Cursor = Cursors.Default;
						break;
					default:
						this.Cursor = Cursors.Default;
						break;
				}
			}
		}

		private void MouseClick_Client(int x, int y)
		{
			if(this.MyMode == GameModes.Client && ActiveClient != null && ActiveClient.PlayerNumber == this.PlayerTurn)
			{
				switch(ActiveClient.Handle_MouseClick(x, y, this.MySelectedObjects))
				{
					case Client.ClickState.OK:
						this.Cursor = Cursors.Default;
						break;
					case Client.ClickState.Invalid:
						this.Cursor = Cursors.Default;
						break;
					default:
						this.Cursor = Cursors.Default;
						break;
				}
			}
		}

		private void MouseRelease_Client(int x, int y)
		{
			if(this.MyMode == GameModes.Client && ActiveClient != null && ActiveClient.PlayerNumber == this.PlayerTurn)
			{
				switch(ActiveClient.Handle_MouseRelease(x, y, this.MySelectedObjects))
				{
					case Client.ReleaseState.OK:
						this.Cursor = Cursors.Default;
						break;
					case Client.ReleaseState.Invalid:
						ActiveClient.ReleaseObject();
						this.Cursor = Cursors.Default;
						break;
				}
			}
		}

		/*private void ResetWall(Wall w)
		{
			w.Color.Alpha = Colors.Wallpaper2.Alpha;
			if(ActiveClient.PlayerNumber == 1)
			{
				w.MoveTo(Wall.Orientations.Horizontal, new Point3Df(9 * 1.25f, (w.Index-1) * 1.25f - 0.25f, 0.16f ));
				w.MoveTowardDestination(0.99f);
			}
			else
			{
				w.MoveTo(Wall.Orientations.Horizontal, new Point3Df(-2.50f, (w.Index-1) * 1.25f - 0.25f, 0.16f ));
				w.MoveTowardDestination(0.99f);
			}
		}*/
			

		private void oglControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			this.MyMouse.Location.X = e.X;
			this.MyMouse.Location.Y = e.Y;
			UpdateSelectedObjectList(e.X, e.Y);
			if(this.MyMode == GameModes.Client && ActiveClient != null)
			{
				if(ActiveClient.MoveState == Client.MoveStates.ChooseStart && ActiveClient.PickedObject != null)
				{
					ActiveClient.ReleaseObject();
				}

				if(ActiveClient.PickedObject == null)
				{
					MouseHover_Client(e.X, e.Y);
				}
				else
				{
					MouseDrag_Client(e.X, e.Y);
				}
			}

			if (this.myArcball.MouseDown && this.MyMode != GameModes.GameOver && this.MyMode != GameModes.NoGame)
			{
				Kevin.Arcball.Quat4fT quat = this.myArcball.Drag(e.X, e.Y);

				this.ThisRot = quat.Get3x3RotationMatrix;
				this.ThisRot = this.ThisRot * this.LastRot;
				this.Transform.SetRotationFromMatrix3f(this.ThisRot);

/*				myArcball.drag(&myMousePt, &ThisQuat);						// Update End Vector And Get Rotation As Quaternion
				Matrix3fSetRotationFromQuat4f(&ThisRot, &ThisQuat);		// Convert Quaternion Into Matrix3fT
				Matrix3fMulMatrix3f(&ThisRot, &LastRot);				// Accumulate Last Rotation Into This One
				Matrix4fSetRotationFromMatrix3f(&Transform, &ThisRot);	// Set Our Final Transform's Rotation From This One*/

			}
		}

		private void oglControl_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			int clicks = e.Delta * SystemInformation.MouseWheelScrollLines / 120;

			if (clicks != 0)
			{
				this.MyCamera.MoveTo(MyCamera.Dest.Eye.X, MyCamera.Dest.Eye.Y, MyCamera.Dest.Eye.Z - (0.125f * clicks),
					MyCamera.Dest.At.X, MyCamera.Dest.At.Y, MyCamera.Dest.At.Z,
					MyCamera.Dest.Up.X, MyCamera.Dest.Up.Y, MyCamera.Dest.Up.Z);
			}
		}
		
		private void oglControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(e.Button == MouseButtons.Left)
			{
				this.MyMouse.Left.Click(e.X, e.Y);
				if(this.MyMode == GameModes.Client)
				{
					MouseClick_Client(e.X, e.Y);
				}
			}
			else if (e.Button == MouseButtons.Right)
			{
				if(ActiveClient != null && ActiveClient.MoveState == Client.MoveStates.ChooseEnd && ActiveClient.PickedObject != null && ActiveClient.PickedObject is Wall)
				{
					Wall w = (Wall)ActiveClient.PickedObject;
					if(w.Orientation == Wall.Orientations.Horizontal)
					{
						w.Orientation = Wall.Orientations.Vertical;
					}
					else
					{
						w.Orientation = Wall.Orientations.Horizontal;
					}
				}
				else if (this.MyMode != GameModes.GameOver && this.MyMode != GameModes.NoGame)
				{
					this.myArcball.Click(e.X, e.Y);
				}
			}
		}

		private void oglControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(e.Button == MouseButtons.Left)
			{
				MyMouse.Left.Release();
				if(this.MyMode == GameModes.Client)
				{
					MouseRelease_Client(e.X, e.Y);
				}
			}
			else if (e.Button == MouseButtons.Right)
			{
				MyMouse.Right.Release();
				myArcball.Release();
			}
		}

		private void oglControl_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
		{
			//Net.Client c = (Net.Client)this.playerList[0];

			if (e.KeyChar == 'a')
			{
				this.MyCamera.MoveTo(MyCamera.Pos.Eye.X - 0.5f, MyCamera.Pos.Eye.Y, MyCamera.Pos.Eye.Z);
				//c.SendMessage("move left");
			}
			else if (e.KeyChar == 'd')
			{
				this.MyCamera.MoveTo(MyCamera.Pos.Eye.X + 0.5f, MyCamera.Pos.Eye.Y, MyCamera.Pos.Eye.Z);
				//c.SendMessage("move right");
			}
			else if (e.KeyChar == 's')
			{
				this.MyCamera.MoveTo(MyCamera.Pos.Eye.X, MyCamera.Pos.Eye.Y - 0.5f, MyCamera.Pos.Eye.Z);
				//c.SendMessage("move down");
			}
			else if (e.KeyChar == 'w')
			{
				//c.SendMessage("move up");
				this.MyCamera.MoveTo(MyCamera.Pos.Eye.X, MyCamera.Pos.Eye.Y + 0.5f, MyCamera.Pos.Eye.Z);
			}
			else if (e.KeyChar == 'r')
			{
				//c.SendMessage("placehwall 5 5");
			}

			//MessageBox.Show("Blah", "Blah", MessageBoxButtons.OK, MessageBoxIcon.Information);
			//e.Handled=true;
		}


		private void UpdateSelectedObjectList(float x, float y)
		{
			const int BUFFER_SIZE = 256;
			int [] selectBuf = new int[BUFFER_SIZE];
			Gl.glSelectBuffer(BUFFER_SIZE, selectBuf);
			
			int [] viewpCoords = new int[4];
			Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewpCoords);	// Get the current view port coordinates

			Gl.glMatrixMode(Gl.GL_PROJECTION);

			Gl.glPushMatrix();
			Gl.glRenderMode(Gl.GL_SELECT);
			Gl.glLoadIdentity();								// Reset our projection matrix

			Glu.gluPickMatrix(x, viewpCoords[3]-y, 2, 2, viewpCoords);

			Glu.gluPerspective( 45, (double)oglControl.Width/ (oglControl.Height > 0 ? (double)oglControl.Height : 1), 1, 120);

			Gl.glMatrixMode(Gl.GL_MODELVIEW);

			RenderScene();

			int hits = Gl.glRenderMode(Gl.GL_RENDER);

			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glPopMatrix();

			Gl.glMatrixMode(Gl.GL_MODELVIEW);

			ArrayList hitList = new ArrayList();
			this.MySelectedObjects.Clear();
			this.MySelectedObjects.Add(null);
			
			if (hits > 0)
			{
				int lowestDepth = selectBuf[1];
				int selectedObj = selectBuf[3];
				hitList.Add(selectedObj);

				for(int i=1; i < hits; i++)
				{
					if(selectBuf[(i * 4) + 1] < lowestDepth)
					{
						// Set the current lowest depth
						lowestDepth = selectBuf[(i * 4) + 1];

						// Set the current object ID
						selectedObj = selectBuf[(i * 4) + 3];
						hitList.Add(selectedObj);
					}
				}

				if (hitList.Count > 0)
				{
					foreach(int i in hitList)
					{
						object O = Geometry.Namestack.al[i];
					
						if (O != null)
						{
							this.MySelectedObjects.Add(O);
						}
					}
				}
			}
			else
			{
				return;
			}
		}
		
		private void drawHUD()
		{
			setOrthographicProjection();
			Gl.glPushMatrix();
			Gl.glLoadIdentity();
			//renderBitmapString(5.0f, 5.0f, Glut.GLUT_BITMAP_HELVETICA_18, "3D Tech");
			Gl.glPopMatrix();
			resetPerspectiveProjection();
		}

		void renderBitmapString(float x, float y, System.IntPtr font, string s)
		{
			Gl.glRasterPos3f(x, y, 0.0f);
			foreach(char c in s)
			{
				if (c != 255)
				{
					Glut.glutBitmapCharacter(font, c);
				}
			}
		}

		public void DrawHUD()
		{
			setOrthographicProjection();
			Gl.glPushMatrix();
			Gl.glLoadIdentity();

			Gl.glBegin(Gl.GL_QUADS);

			Gl.glColor3f(0.8f, 0.84f, 1.0f);
			Gl.glVertex2d(0, 0);

			Gl.glColor3f(0.6f, 0.7f, 1.0f);
			Gl.glVertex2d(oglControl.Width, 0);

			Gl.glColor3f(0.5f, 0.59f, 0.8f);
			Gl.glVertex2d(oglControl.Width, oglControl.Height);
			
			Gl.glColor3f(0.6f, 0.7f, 1.0f);
			Gl.glVertex2d(0, oglControl.Height);

			Gl.glPopMatrix();
			this.resetPerspectiveProjection();
		}


		void setOrthographicProjection()
		{
			// switch to projection mode
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			// save previous matrix which contains the 
			//settings for the perspective projection
			Gl.glPushMatrix();
			// reset matrix
			Gl.glLoadIdentity();
			// set a 2D orthographic projection
			Glu.gluOrtho2D(0, this.oglControl.Width, 0, this.oglControl.Height);
			// invert the y axis, down is positive
			Gl.glScalef(1.0f, -1.0f, 1.0f);
			// mover the origin from the bottom left corner
			// to the upper left corner
			Gl.glTranslatef(0.0f, -this.oglControl.Height, 0.0f);
			Gl.glMatrixMode(Gl.GL_MODELVIEW);
		}

		void resetPerspectiveProjection() 
		{
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glPopMatrix();
			Gl.glMatrixMode(Gl.GL_MODELVIEW);
		}

		private bool needsUpdate=false;
		private void timer1_Tick(object sender, System.EventArgs e)
		{
			needsUpdate = false;

			if(this.Server != null && this.Server.Board != null)
			{
				if(this.Server.Board.Update(0.1f) == true)
				{
					needsUpdate = true;
				}
			}

			if(this.playerList.Count > 0)
			{
				foreach(Client c in this.playerList)
				{
					if(c != null && c.Board != null)
					{
						if(c.Board.Update(0.1f) == true)
						{
							needsUpdate = true;
						}
					}
				}
			}
			
			if(MyMode == GameModes.Client || MyMode == GameModes.Server)
			{
				if (MyCamera.Moving)
				{
					if(MyCamera.MoveTowardDestination(0.25f))
					{
						needsUpdate  = true;
					}
				}
			}
			else if (this.MyMode == GameModes.GameOver || MyMode == GameModes.NoGame)
			{
				this.nextChange--;

				if(this.nextChange <= 0)
				{
					this.nextChange = rand.Next(150) + 50;
					this.MyCamera.Source.Eye.X = rand.Next(-10, 10);
					this.MyCamera.Source.Eye.Y = rand.Next(-10, 10);
					this.MyCamera.Source.Eye.Z = rand.Next(3, 22);

					this.MyCamera.Dest.Eye.X = rand.Next(-10, 10);
					this.MyCamera.Dest.Eye.Y = rand.Next(-10, 10);
					this.MyCamera.Dest.Eye.Z = rand.Next(10, 22);
					this.MyCamera.Alpha = 0.0f;
					this.MyCamera.Moving = true;
				}

/*				if(this.Server != null && this.Server.Board != null)
				{
					if(this.Server.Board.Update(0.1f) == true)
					{
						needsUpdate  = true;
					}
				}*/

				if (MyCamera.Moving && MyCamera.MoveTowardDestination(0.01f))
				{
					needsUpdate  = true;
				}
			}

			if(needsUpdate)
			{
				this.oglControl.Invalidate();
			}
		}

		private void oglControl_MouseHover(object sender, System.EventArgs e)
		{
			//System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();
			//ToolTip1.SetToolTip(this., "Hello");
		}

		private void Console_OnEvent(object sender, string text)
		{
			if(MyMode == GameModes.Client && ActiveClient != null)
			{
				ActiveClient.SendMessage(text);
			}
			else if (MyMode == GameModes.Server)
			{
				this.Server.MessageAll(text);
			}
		}

		private void menuQHelp_Click(object sender, System.EventArgs e)
		{
			try
			{
				System.Diagnostics.Process proc = new System.Diagnostics.Process();
				proc.EnableRaisingEvents=false;
				proc.StartInfo.FileName="help.html";
				proc.Start();
			}
			catch(Exception)
			{
				MessageBox.Show("Could not show help. To view help, find help.html.", "Help Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
		}

	}

	public class Text
	{
		public const string AlreadyActive = "cannot activate; server is already active";
		public const string AlreadyInactive = "cannot deactivate; server is not active";

		public const string Active = "Now active.";
		public const string Inactive = "Now inactive.";
		public const string ClientLogin = "Receiving client login information...";
		public const string ClientLoginBad = "Receiving login rejected.";
		public const string ClientLoginOK = "Receiving login accepted.";
		public const string ListeningForClients = "Listening for client logins...";
		
		public const string ExpectingClientLogins = "Listening for clients...";
		public const string RecievedClientLogins = "Clients Connected.";

		public const string Online = "Server Online.";
		public const string Offline = "Server Offline.";

		public const string ClientConnected = "Client Connected.";
		public const string ClientDisconnected = "Client Disconnected.";

		public const string Ready = "Ready.";

		public const string Player1Turn = "It is Player 1's turn.";
		public const string Player2Turn = "It is Player 2's turn.";

		public const string SettingsFile = "settings.file";
	}

}
