//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;

namespace CommunityServer.Components
{
	/// <summary>
	/// Summary description for JavaScript.
	/// </summary>
	public class JavaScript
	{
		private JavaScript()
		{
		}

		public static string Encode(string text)
		{
			return text.Replace("\\", "\\\\").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\'", "\\\'").Replace("\"", "\\\"");
		}

		public static void RegisterToolTips(Page page)
		{
			string url = Globals.GetSiteUrls().Locations["Utility"] + "wz_tooltip.js";
			page.RegisterStartupScript("ToolTips", string.Format("<script src=\"{0}\" type=\"text/javascript\"></script>", url));
		}

		public static string ToolTipText(string tip, int width)
		{
			return string.Format("this.T_WIDTH={0};return escape('{1}')", width.ToString(), tip);
		}

		public static void RegisterControlForToolTip(System.Web.UI.IAttributeAccessor cntrl, string tip, int width)
		{
			cntrl.SetAttribute("onmouseover", ToolTipText(tip,width));
			//cntrl.Attributes.Add("onmouseover", ToolTipText(tip,width));
		}

		//Refresh based on: http://grizzlyweb.com/webmaster/javascripts/refresh.asp

		/// <summary>
		/// Enables a single javascript method refresh() to be used to refresh the page
		/// </summary>
		/// <param name="page"></param>
		public static void RegisterRefresh(Page page)
		{
			page.RegisterClientScriptBlock("CS.Refresh",Refresh(page.Request.Url));
		}

		/// <summary>
		/// Enables a single javascript method refresh(sURL) to be used to refresh the page
		/// </summary>
		/// <param name="page"></param>
		public static void RegisterRefreshURL(Page page)
		{
			page.RegisterClientScriptBlock("CS.RefreshURL",RefreshURL());
		}

		/// <summary>
		/// Returns the javascript code blocks to render the 3 levels of refreshes
		/// </summary>
		/// <param name="pageUrl"></param>
		/// <returns></returns>
		public static string Refresh(Uri pageUrl)
		{
			StringBuilder sb = new StringBuilder();
			sb.Append("<script language=\"JavaScript\">");
			sb.Append("\n<!--");
			sb.AppendFormat("\nvar sURL = '{0};'",pageUrl.ToString());
			sb.Append("\nfunction refresh() {window.location.href = sURL;}");
			sb.Append("\n//-->");
			sb.Append("\n</script>");
			sb.Append("\n<script language=\"JavaScript1.1\">");
			sb.Append("\n<!--");
			sb.Append("\nfunction refresh(){window.location.replace( sURL );}");
			sb.Append("\n//-->");
			sb.Append("\n</script>");
			sb.Append("\n<script language=\"JavaScript1.2\">");
			sb.Append("\n<!--");
			sb.Append("\nfunction refresh() { window.location.reload( false );}");
			sb.Append("\n//-->");
			sb.Append("\n</script>");
            sb.Append("\n<script language=\"JavaScript\">");
            sb.Append("\n<!--");
            sb.Append("\nfunction refreshCallback(res) { if(res){refresh();} }");
            sb.Append("\n//-->");
            sb.Append("\n</script>");

			return sb.ToString();
		}

		/// <summary>
		/// Returns the javascript code blocks to render the 3 levels of refreshes
		/// The URL will be supplied at run-time
		/// </summary>
		/// <returns></returns>
		public static string RefreshURL()
		{
			StringBuilder sb = new StringBuilder();
			sb.Append("<script language=\"JavaScript\">");
			sb.Append("\n<!--");
			sb.Append("\nfunction refreshURL(sURL) {window.location.href = sURL;}");
			sb.Append("\n//-->");
			sb.Append("\n</script>");
			sb.Append("\n<script language=\"JavaScript1.1\">");
			sb.Append("\n<!--");
			sb.Append("\nfunction refreshURL(sURL){window.location.replace( sURL );}");
			sb.Append("\n//-->");
			sb.Append("\n</script>");
			sb.Append("\n<script language=\"JavaScript1.2\">");
			sb.Append("\n<!--");
			sb.Append("\nfunction refreshURL(sURL) {window.location.replace( sURL );}");
			sb.Append("\n//-->");
			sb.Append("\n</script>");

            sb.Append("\n<script language=\"JavaScript\">");
            sb.Append("\n<!--");
            sb.Append("\nfunction refreshCallback(res) { if(res){refresh();} }");
            sb.Append("\n//-->");
            sb.Append("\n</script>");

			return sb.ToString();
		}


		public static void RenderAsJavaScript(HttpContext context)
		{
			context.Response.Filter = new JavaScriptResponseFilter(context);
		}

		public class JavaScriptResponseFilter : Stream
		{
			private static Regex findUrls = new Regex("(href|src)=\"?([^ \"]{1,})\"?", RegexOptions.IgnoreCase | RegexOptions.Compiled);

			private Stream stream;
			private StreamWriter streamWriter;
			private long position;
			private string baseUrl;
		
			public JavaScriptResponseFilter(HttpContext context)
			{
				context.Response.Clear();
				context.Response.ContentType = "text/javascript";

				this.stream = context.Response.Filter;
				this.streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);

				Uri uri = context.Request.Url;
				this.baseUrl = uri.Scheme + "://" + uri.Host + (uri.IsDefaultPort ? "" : ":" + uri.Port.ToString());
			}
		
			public override void Write(byte[] buffer, int offset, int count)
			{
				MemoryStream ms = new MemoryStream(buffer, offset, count, false);
				StreamReader sr = new StreamReader(ms, System.Text.Encoding.UTF8);
				string s;
				while ((s = sr.ReadLine()) != null)
				{
					streamWriter.Write("document.write(\"");
					streamWriter.Write(JavaScript.Encode(ResolveUrls(s)));
					streamWriter.Write("\");\n");
				}
				streamWriter.Flush();
			}

			public virtual string ResolveUrls(string html)
			{
				Match m = findUrls.Match(html);
				int lastIndex = 0;
				StringBuilder newHtml = new StringBuilder();

				while (m != null && m.Success)
				{
					if (m.Index != lastIndex)
						newHtml.Append(html.Substring(lastIndex, m.Index - lastIndex));

					newHtml.Append(m.Groups[1].Value);
					newHtml.Append("=\"");

					if (m.Groups[2].Value.Substring(0, 1) == "/")
					{
						newHtml.Append(baseUrl);
						newHtml.Append(m.Groups[2].Value);
					}
					else
						newHtml.Append(m.Groups[2].Value);

					newHtml.Append("\"");

					lastIndex = m.Index + m.Length;
					m = findUrls.Match(html, lastIndex + 1);
				}

				if (lastIndex != html.Length - 1)
					newHtml.Append(html.Substring(lastIndex));

				return newHtml.ToString();
			}

			#region Stream overrides
		
			public override bool CanRead 
			{
				get { return true; }
			}

			public override bool CanSeek 
			{
				get { return true; }
			}

			public override bool CanWrite 
			{
				get { return true; }
			}

			public override void Close() 
			{
				streamWriter.Close();
				stream.Close();
			}

			public override void Flush() 
			{
				streamWriter.Flush();
				stream.Flush();
			}
  
			public override long Length 
			{
				get { return 0; }
			}

			public override long Position 
			{
				get { return position; }
				set { position = value; }
			}

			public override long Seek(long offset, System.IO.SeekOrigin direction) 
			{
				return stream.Seek(offset, direction);
			}

			public override void SetLength(long length) 
			{
				stream.SetLength(length);
			}

			public override int Read(byte[] buffer, int offset, int count) 
			{
				return stream.Read(buffer, offset, count);
			}

			#endregion
		}
	}
}
