using System;
using System.IO;
using System.Xml;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Xml.Serialization;
using XYNetSocketLib;
using vclass.appsharing;

namespace vclass.network.client
{
	/// <summary>
	/// This class is created to connect to the server and interact with the server.
	/// </summary>
	/// 	
	/// Author: yavuz
	/// created: 18/03/05
	/// last update: 
	
	public class ClassClient
	{
		private XYNetClient vcClient = null;
		private XYNetCommon xynetCommon = new XYNetCommon();
		private String serverAddress;
		private int serverPort;
		private Thread applicationThread;
		private MainForm mainForm = null;


		public ClassClient(MainForm mf)
		{
			mainForm = mf;
			//TODO: These will be read from the configuration file!
			XmlDocument doc = new XmlDocument();
			XmlTextReader reader = new XmlTextReader("C:\\configure.xml");
			doc.Load(reader);
			XmlNodeList list = doc.GetElementsByTagName("configure");
				
			serverAddress = list[0].ChildNodes[0].InnerText;
			serverPort = 3232;

			reader.Close();

			vcClient = new XYNetClient(serverAddress, serverPort);
			Console.WriteLine("conencted to " + serverAddress);
			applicationThread = new Thread(new ThreadStart(this.useApplication));
			applicationThread.Start();
			while(!applicationThread.IsAlive);
		}

		public void sendFile(String fileName){
			try
			{
				FileStream fileStream = File.OpenRead(fileName);
				byte[] data = new byte[fileStream.Length + 4];
				fileStream.Read(data, 0, Convert.ToInt32(fileStream.Length) + 4);
				vcClient.SendBinaryData(data);
				fileStream.Close();
			}
			catch(Exception ex){
				Console.WriteLine("Exception occured: " + ex.StackTrace);
			}
		}

		public int connect(String userID, String password){
			try
			{
				if(vcClient.Connect() == false)
				{
					//TODO: return to login form!
					//TODO: well, there is non currently :)...
					//coming soon buhuhhhaaa...
					//write exception to file...
					throw vcClient.GetLastException();
					//cannot connect to server, check server status and server info
				}
				else
				{
					String authenticationXML = "<authentication><userID>"
						+ userID
						+ "</userID><password>"
						+ password
						+ "</password></authentication>";
					if(vcClient.SendStringData(authenticationXML) == false)
					{
						//TODO: you know...
						throw vcClient.GetLastException();
						//could not connect, wrong userID and password...
					}
					else
					{
						//connection established...
						Console.WriteLine("Client connected");
						object[] response = vcClient.ReceiveData();
						if(response[0] == null){
							Console.WriteLine("A string expected...");
							if(response[1] != null){
								XmlDocument doc = new XmlDocument();
								Console.WriteLine("Client got: " + response[1].ToString());
								doc.LoadXml(response[1].ToString());
								XmlElement root = doc.DocumentElement;
								if(root.LocalName.Equals("authenticationResponse")){
									Console.WriteLine("response " + root.InnerText);
									if((root.InnerText).Equals("1")){
										//login successful
										Console.WriteLine("Login Successful...");
										return 1;
									}
									//login failed
									Console.WriteLine("Login Failed");
									return 0;
								}
							}

						}
						return 1;
					}
				}
			}
			catch(Exception exc){
				Console.WriteLine(exc.GetType() + "Exception occured " + exc.StackTrace + "\n" + exc.Message + exc.Source);
				return 0;
			}
		}

		public void shareApplication(Image snapshot, int snapshotID){
			try
			{
				//Console.WriteLine("snapshot is " + snapshot);
				XmlDocument doc = new XmlDocument();
				//Create the document structure
				XmlNode snapNode = doc.CreateElement("snapshot");
				XmlNode command = doc.CreateElement("applicationSharing");
				doc.AppendChild(command);
				command.AppendChild(snapNode);

				string data = null;
				using (MemoryStream mem = new MemoryStream())
				{
					snapshot.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
					//Convert the bytes to a string.
					data = Convert.ToBase64String(mem.ToArray());
				}
				snapNode.InnerText = data;
				StringWriter strwrt = new StringWriter();
				doc.Save(strwrt);
//				Console.WriteLine(strwrt.ToString());

//				Console.WriteLine("snapshot string is " + snapshotString);
				
				//XmlSerializer xmlSerializer = new XmlSerializer( typeof(Image));
				//TextWriter xmlWriter = new StreamWriter("c:/dnm.xml");
				//xmlSerializer.Serialize(xmlWriter, snapshot);
				//Console.WriteLine("xml is " + xmlWriter.ToString());
/*				String asXML = "<applicationSharing>"
					+ "<application id=" + snapshotID + ">"
					+	snapshotString
					+ "</application></applicationSharing>";
				Console.WriteLine("Application Sharing XML is " + asXML);
*/				if(vcClient.SendStringData(strwrt.ToString()) == false)
				{
					//TODO: you know...
					throw vcClient.GetLastException();
					//could not send snapshot...
				}
			}
			catch(Exception ex){
				Console.WriteLine("share exception " + ex.StackTrace);
			}
		}

		public void useApplication(){
			while(true)
			{
				Console.WriteLine("sleeping for 2 seconds...");
				Thread.Sleep(2000);
				Console.WriteLine("check data...");
				object[] pData = vcClient.ReceiveData();
				// invoke message handler if a message is received
				if(pData!=null) handleMessage((byte[])pData[0], (string)pData[1]);
				else
					Console.WriteLine("no data available...");
				//Thread.Sleep(5000);
			}
		}

		private void handleMessage(byte[] pBinaryMsg, string sStringMsg) 
		{
			Console.WriteLine("Client handles data...");
			if(sStringMsg != null){
				handleStringMessage(sStringMsg);
			}
			else if(pBinaryMsg != null){
				Console.WriteLine("slide received...");
				handleBinaryMessage(pBinaryMsg);
			}
		}   

		private void handleBinaryMessage(byte[] data){
			MemoryStream ms = new MemoryStream(data);
			Image im = Image.FromStream(ms);
			mainForm.updateSlide(im);
		}

		public void sendSlide(Image slide){
			try
			{
				Console.WriteLine("sending slide...");
				FileStream fs = new FileStream("c:/slide_dnm.jpg", System.IO.FileMode.Open);
				//MemoryStream mstream = new MemoryStream();
				//slide.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
				byte[] data = new byte[fs.Length + 4];
				fs.Read(data, 0, Convert.ToInt32(fs.Length) + 4);
				Console.WriteLine("sending slide...2");
				vcClient.SendBinaryData(data);
				Console.WriteLine("sending slide...3");
			}
			catch(Exception ex){
				Console.WriteLine("binary " + ex.StackTrace);
			}
		}

		private void handleStringMessage(string msg){
			//			System.Console.Out.WriteLine("   " + sData);
			XmlDocument doc = new XmlDocument();
			//			Console.WriteLine("Server got: " + sData);
			doc.LoadXml(msg);
			Image appSnapshot = null;
			String action = doc.DocumentElement.LocalName;
			Console.WriteLine("Client action: " + action);
			if(action.Equals("applicationSharing"))
			{
				Console.WriteLine("server:sharing application...");
				string data = doc.SelectSingleNode("/applicationSharing/snapshot").InnerText;
				
//				Console.WriteLine("Application data " + data);

				using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(data)))
				{
					try
					{
						//Load the image from the stream.
						FileStream fs = File.OpenWrite("C:/clientAppImage.jpg");
						mem.WriteTo(fs);
						fs.Close();
						Image tmpImage = Image.FromFile("C:/clientAppImage.jpg");
						appSnapshot = new Bitmap(tmpImage.Size.Width, tmpImage.Size.Height);
						Graphics graph = Graphics.FromImage(appSnapshot);
						graph.DrawImage(tmpImage, 0, 0);
						graph.Dispose();
						tmpImage.Dispose();
					}
					catch(Exception e){
						Console.WriteLine("image problem " + e.StackTrace + " " + e.Message);
					}
				}
				//Asign it to a PictureBox
//				appSnapshot.Save("C:/appImage.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
				mainForm.setAppPicture(appSnapshot);

			}
		}

	}
}
