using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Web.Services.Description;
using System.Web.Services.Discovery;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using MonoDevelop.Core;
using MonoDevelop.Components.HtmlControl;
using MonoDevelop.Ide.Gui;
using MonoDevelop.WebReferences;
using Gtk;

namespace MonoDevelop.WebReferences.Dialogs
{
	
	internal class WebReferenceDialog : Gtk.Dialog
	{
		#region Widgets
		protected Gtk.Action btnNext;
		protected Gtk.Action btnBack;
		protected Gtk.Action btnRefresh;
		protected Gtk.Action btnStop;
		protected Gtk.Action btnHome;
		protected Gtk.Button btnGO;
		protected Gtk.Button btnOK;
		protected Gtk.Button btnCancel;
		protected Gtk.Entry tbxNamespace;
		protected Gtk.Entry tbxReferenceName;
		protected Gtk.Entry tbxReferenceURL;
		protected Gtk.Frame frmBrowser;
		protected MozillaControl cstBrowser = new MozillaControl();
		#endregion
		
		#region Properties
		/// <summary>Gets or Sets whether the current location of the browser is a valid web service or not.</summary>
		/// <value>True if the current location of the browser is a Web Service, otherwise false.</value>
		public bool IsWebService
		{
			get { return btnOK.Sensitive; }
			set 
			{
				// Clear out the Reference and Namespace Entry
				if (btnOK.Sensitive && !value)
				{
					this.tbxReferenceName.Text = "";
				}
				btnOK.Sensitive = value;
				tbxReferenceName.Sensitive = value;
			}
		}
		
		/// <summary>Gets or Sets the current url for web service</summary>
		/// <value>A string containing the url of the web service</value>
		public string ServiceUrl
		{
			get { return serviceUrl; }
			set { serviceUrl = value; }
		}
		
		/// <summary>Gets or Sets the namespace prefix for the web service</summary>
		/// <value>A string containing namespace prefix value for the web service</value>
		public string NamespacePrefix
		{
			get { return namespacePrefix; }
			set { namespacePrefix = value; }
		}
		
		/// <summary>Gets the default namespace for the web service based of the service url and namespace prefix</summary>
		/// <value>A string containing default namespace for the web service</value>
		public string DefaultNamespace
		{
			get { return namespacePrefix; }
		}
		
		/// <summary>Gets the default reference name for the web service based of the service url</summary>
		/// <value>A string containing default reference name for the web service</value>
		public string DefaultReferenceName
		{
			get
			{
				Uri discoveryUri = new Uri(this.ServiceUrl);
				if (discoveryUri != null)
					return discoveryUri.Host;
				else
					return String.Empty;
			}
		}
		
		/// <summary>Gets the name for the web reference.</summary>
		/// <value>A string containing the name for the web reference.</value>
		public string ReferenceName
		{
			get { return this.tbxReferenceName.Text; }
		}
		
		/// <summary>Gets the namespace for the web reference.</summary>
		/// <value>A string containing the namespace for the web refrence.</value>
		public string Namespace
		{
			get { return this.tbxNamespace.Text; }
		}
		
		/// <summary>Gets the selected service discovery client protocol.</summary>
		/// <value>A DiscoveryClientProtocol containing the web reference information.</value>
		public DiscoveryClientProtocol SelectedService
		{
			get { return selectedService; }
		}
		
		/// <summary>Gets or Sets the the base path of the where the web reference.</summary>
		/// <value>A string containing the base path where all the web references are stored in.</summary>
		public string BasePath
		{
			get { return basePath; }
			set { basePath = value; }
		}
		
		/// <summary>Gets the the base path for the current reference.</summary>
		/// <value>A string containing the base path for the current reference.</summary>
		public string ReferencePath
		{
			get { return System.IO.Path.Combine(BasePath, ReferenceName); }
		}
		#endregion
		
		#region Member Variables
		private string homeUrl = "http://www.w3schools.com/WebServices/TempConvert.asmx";
		private string serviceUrl = "";
		private string namespacePrefix = "";
		private DiscoveryClientProtocol selectedService;
		private string basePath = "";
		protected Gtk.Alignment frmBrowserAlign;
		#endregion
		
		/// <summary>Initializes a new instance of the AddWebReferenceDialog widget.</summary>
		public WebReferenceDialog(string basePath)
		{
			Stetic.Gui.Build(this, typeof(MonoDevelop.WebReferences.Dialogs.WebReferenceDialog));
			this.basePath = basePath;
			this.IsWebService = false;
			
			// Add the mozilla control to the frame
			cstBrowser.LocChange += new EventHandler(Browser_LocationChanged);
			cstBrowser.NetStart += new EventHandler(Browser_StartLoading);
			cstBrowser.NetStop += new EventHandler(Browser_StopLoading);
			frmBrowser.Add(cstBrowser);
			cstBrowser.LoadUrl(this.homeUrl);
			cstBrowser.Show();
			frmBrowser.Show();
			this.ShowAll();
		}
		
		/// <summary>Execute the event when any of the buttons on the action panel has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_URLKeyReleased (object sender, EventArgs e)
		{
			if (sender.Equals(btnOK) && Directory.Exists(this.ReferencePath))
			{
				string message = String.Format("The referene name '{0}' already exists.", this.ReferenceName);
				IdeApp.Services.MessageService.ShowWarning(message);
				return;	
			}
			else
			{
				Respond((sender.Equals(btnOK)) ? Gtk.ResponseType.Ok : Gtk.ResponseType.Cancel);
				Destroy();
			}
		}
		
		/// <summary>Execute the event when the Browser Go button has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_GoButtonClicked (object sender, EventArgs e)
		{
			cstBrowser.LoadUrl(tbxReferenceURL.Text);
		}
		
		/// <summary>Execute the event when the Enter key has been pressed on the Url Entry</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_URLKeyReleased (object sender, Gtk.KeyReleaseEventArgs e)
		{
			if (e.Event.Key == Gdk.Key.Return)
			{
				cstBrowser.LoadUrl(tbxReferenceURL.Text);
			}
		}
		
		/// <summary>Execute the event when the Location of the Browser has changed</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_LocationChanged (object sender, EventArgs e)
		{
			this.tbxReferenceURL.Text = this.cstBrowser.Location;
			this.btnBack.Sensitive = cstBrowser.CanGoBack();
			this.btnNext.Sensitive = cstBrowser.CanGoForward();
			// Query the current url for services
			ThreadPool.QueueUserWorkItem(new WaitCallback(QueryService), this.tbxReferenceURL.Text);
		}
		
		/// <summary>Execute when the browser starts loading a document</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_StartLoading (object sender, EventArgs e)
		{
			this.btnStop.Sensitive = true;
		}
		
		/// <summary>Execute the browser stop loading a document</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_StopLoading (object sender, EventArgs e)
		{
			this.btnStop.Sensitive = false;
		}
		
		/// <summary>Execute when the Back button has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_BackButtonClicked (object sender, EventArgs e)
		{
			this.cstBrowser.GoBack();
		}
		
		/// <summary>Execute when the Next button has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_NextButtonClicked (object sender, EventArgs e)
		{
			this.cstBrowser.GoForward();
		}
		
		/// <summary>Execute when the Refresh button has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_RefreshButtonClicked (object sender, EventArgs e)
		{
			this.cstBrowser.Reload(0);
		}
		
		/// <summary>Execute when the Stop button has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_StopButtonClicked (object sender, EventArgs e)
		{
			this.cstBrowser.StopLoad();
		}
		
		/// <summary>Execute when the Home button has been clicked</summary>
		/// <param name="sender">An object that contains the sender data.</param>
		/// <param name="e">An EventArgs object that contains the event data.</param>
		private void Browser_HomeButtonClicked (object sender, EventArgs e)
		{
			this.cstBrowser.LoadUrl(this.homeUrl);
		}
		
		/// <summary>Queries the web service to validate that the current url contains services</summary>
		/// <param name="param">An object that contains the parameter being passed from the ThreadPool.</param>
		private void QueryService (object param)
		{
			string url = param as string;
			// Set the service url
			lock (this)
			{
				if (serviceUrl == url) 
					return;
				serviceUrl = url; 
			}
			
			// Checks the availablity of any services
			DiscoveryClientProtocol protocol = new DiscoveryClientProtocol ();
			try
			{
				protocol.DiscoverAny (url);
				// Set the Default Namespace and Reference
				this.tbxNamespace.Text = this.DefaultNamespace;
				this.tbxReferenceName.Text = this.DefaultReferenceName;
				this.IsWebService = true;
				this.selectedService = protocol;
				
//				object doc = protocol.Documents [url];
//				if (doc  is ServiceDescription)
//					this.RenderBrowserData(new object[2] { Library.GenerateWsdlXml(protocol), "wsdl.html" });
//				else if (doc is DiscoveryDocument)
//					this.RenderBrowserData(new object[2] { Library.GenerateDiscoXml((DiscoveryDocument)doc), "disco.html" });
				return;
			}
			catch (Exception)
			{
				this.IsWebService = false;
				this.selectedService = null;
				return;
			}
		}
		
//		private void RenderBrowserData (object param)
//		{
//			object[] parameters = param as object[];
//			try
//			{
//				// Load the specified resource as an XslTransform class
//				Stream stream = GetType().Assembly.GetManifestResourceStream ((string)parameters[1]);
//				XmlTextReader reader = new XmlTextReader (stream);
//				XslTransform xslt = new XslTransform ();
//				xslt.Load (reader, null, null);
//				
//				// Transform Html
//				StringWriter htmlWriter = new StringWriter ();
//				xslt.Transform ((XmlDocument)parameters[0], null, htmlWriter, null);
//				this.cstBrowser.RenderData(htmlWriter.ToString(), this.ServiceUrl, "text/html");
//				htmlWriter.Close();
//				htmlWriter.Dispose();
//			}
//			catch (Exception exception)
//			{
//				Console.WriteLine(exception.Message);
//			}
//		}
	}
	
}
