using System;
using System.Collections;
using System.IO;
using System.Web.UI;

namespace flash
{
	/// <summary>
	/// FetchHtmlWriter 获取 aspx 页面所呈现的 html 代码，并存入 streamWriter 指定的文件中
	/// </summary>
	/// <example>
	/// public class Index : System.Web.UI.Page
	/// {
	///		// 复写 Index 类 Render 方法
	///		protected override void Render(HtmlTextWriter writer)
	///		{
	///			// 声明文本输出流
	///			StreamWriter streamWriter=new StreamWriter(@"Index.html", false);
	///
	///			// 输出 HTML 到屏幕设备，并将代码存入文本输出流
	///			base.Render(new FetchHtmlWriter(writer, streamWriter));
	///
	///			// 刷新文本输出流，写出静态文档
	///			streamWriter.Flush();
	///			streamWriter.Close();
	///		}
	///	}
	/// </example>
	public class FetchHtmlWriter : HtmlTextWriter
	{
		// HTML 输出流
		private HtmlTextWriter htmlTextWriter=null;
		// 文本数据流
		private StreamWriter streamWriter=null;
		// HTML 标签属性
		private Hashtable attributes=new Hashtable();
		// HTML 样式
		private Hashtable styles=new Hashtable();

		#region 类 CustomHtmlWriter 构造器
		/// <summary>
		/// 类 FetchHtmlWriter 参数构造器
		/// </summary>
		/// <param name="htmlTextWriter">HTML 输出流</param>
		/// <param name="streamWriter">文本输出流</param>
		public FetchHtmlWriter(HtmlTextWriter htmlTextWriter, StreamWriter streamWriter) : base(htmlTextWriter)
		{
			this.htmlTextWriter=htmlTextWriter;
			this.streamWriter=streamWriter;
		}
		#endregion

		#region 复写 HtmlTextWriter 成员函数
		/// <summary>
		/// 添加属性到输出流
		/// </summary>
		/// <param name="name">属性名</param>
		/// <param name="value">属性值</param>
		public override void AddAttribute(string name, string value)
		{
			this.attributes.Add(name, value);
			this.htmlTextWriter.AddAttribute(name, value);
		}

		/// <summary>
		/// 添加属性到输出流
		/// </summary>
		/// <param name="name">属性名</param>
		/// <param name="value">属性值</param>
		/// <param name="fEncode">是否为 HTML 编码</param>
		public override void AddAttribute(string name, string value, bool fEncode)
		{
			this.attributes.Add(name, this.EncodeAttributeValue(value, fEncode));
			this.htmlTextWriter.AddAttribute(name, value, fEncode);
		}

		/// <summary>
		/// 添加属性到输出流
		/// </summary>
		/// <param name="key">属性键</param>
		/// <param name="value">属性值</param>
		public override void AddAttribute(HtmlTextWriterAttribute key, string value)
		{
			this.attributes.Add(key.ToString(), value);
			this.htmlTextWriter.AddAttribute(key, value);
		}

		/// <summary>
		/// 添加属性到输出流
		/// </summary>
		/// <param name="key">属性键</param>
		/// <param name="value">属性值</param>
		/// <param name="fEncode">是否为 HTML 编码</param>
		public override void AddAttribute(HtmlTextWriterAttribute key, string value, bool fEncode)
		{
			this.attributes.Add(key.ToString(), this.EncodeAttributeValue(value, fEncode));
			this.htmlTextWriter.AddAttribute(key, value, fEncode);
		}

		/// <summary>
		/// 添加 CSS 属性到输出流
		/// </summary>
		/// <param name="name">属性名</param>
		/// <param name="value">属性值</param>
		public override void AddStyleAttribute(string name, string value)
		{
			this.styles.Add(name, value);
			this.htmlTextWriter.AddAttribute(name, value);
		}

		/// <summary>
		/// 添加 CSS 属性到输出流
		/// </summary>
		/// <param name="key">属性键</param>
		/// <param name="value">字符串值</param>
		public override void AddStyleAttribute(HtmlTextWriterStyle key, string value)
		{
			this.styles.Add(key.ToString(), value);
			this.htmlTextWriter.AddStyleAttribute(key, value);
		}

		/// <summary>
		/// 绘制开始标记，例如：<body bgcolor="#ffffff">
		/// </summary>
		/// <param name="tagName">要绘制的开始标记名称</param>
		public override void RenderBeginTag(string tagName)
		{
			base.PushEndTag(tagName);

			this.htmlTextWriter.RenderBeginTag(tagName);
			this.streamWriter.Write("<"+tagName);

			this.RenderStyleAttribute();
		}

		/// <summary>
		/// 绘制开始标记，例如：<body bgcolor="#ffffff">
		/// </summary>
		/// <param name="tagKey">要绘制的开始标记键</param>
		public override void RenderBeginTag(HtmlTextWriterTag tagKey)
		{
			base.PushEndTag(tagKey.ToString());

			this.htmlTextWriter.RenderBeginTag(tagKey);
			this.streamWriter.Write("<"+tagKey.ToString());

			this.RenderStyleAttribute();
		}

		/// <summary>
		/// 绘制结束标记，例如：</html>
		/// </summary>
		public override void RenderEndTag()
		{
			this.htmlTextWriter.RenderEndTag();
			this.streamWriter.Write("</"+base.PopEndTag()+">");	
		}

		/// <summary>
		/// 输出布尔值
		/// </summary>
		/// <param name="value">要输出的布尔值</param>
		public override void Write(bool value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出字符
		/// </summary>
		/// <param name="value">要输出的字符值</param>
		public override void Write(char value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出字符数组
		/// </summary>
		/// <param name="buffer">要输出的字符数组</param>
		public override void Write(char[] buffer)
		{
			this.htmlTextWriter.Write(buffer);
			this.streamWriter.Write(buffer);
		}

		/// <summary>
		/// 输出字符数组
		/// </summary>
		/// <param name="buffer">要输出的字符数组</param>
		/// <param name="index">起始位置</param>
		/// <param name="count">输出个数</param>
		public override void Write(char[] buffer, int index, int count)
		{
			this.htmlTextWriter.Write(buffer, index, count);
			this.streamWriter.Write(buffer, index, count);
		}

		/// <summary>
		/// 输出十进制数
		/// </summary>
		/// <param name="value">要输出的十进制数值</param>
		public override void Write(decimal value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出双精度数
		/// </summary>
		/// <param name="value">要输出的双精度数值</param>
		public override void Write(double value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出单精度数
		/// </summary>
		/// <param name="value">要输出的单精度数值</param>
		public override void Write(float value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出整形数
		/// </summary>
		/// <param name="value">要输出的整形数值</param>
		public override void Write(int value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出长整形数
		/// </summary>
		/// <param name="value">要输出的长整形数值</param>
		public override void Write(long value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出 Object
		/// </summary>
		/// <param name="value">要输出的 Object 值</param>
		public override void Write(object value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出字符串
		/// </summary>
		/// <param name="format">字符串格式</param>
		/// <param name="arg0">格式化参数 0</param>
		public override void Write(string format, object arg0)
		{
			this.htmlTextWriter.Write(format, arg0);
			this.streamWriter.Write(format, arg0);
		}

		/// <summary>
		/// 输出字符串
		/// </summary>
		/// <param name="format">字符串格式</param>
		/// <param name="arg0">格式化参数 0</param>
		/// <param name="arg1">格式化参数 1</param>
		public override void Write(string format, object arg0, object arg1)
		{
			this.htmlTextWriter.Write(format, arg0, arg1);
			this.streamWriter.Write(format, arg0, arg1);
		}

		/// <summary>
		/// 输出字符串
		/// </summary>
		/// <param name="format">字符串格式</param>
		/// <param name="arg0">格式化参数 0</param>
		/// <param name="arg1">格式化参数 1</param>
		/// <param name="arg2">格式化参数 2</param>
		public override void Write(string format, object arg0, object arg1, object arg2)
		{
			this.htmlTextWriter.Write(format, arg0, arg1, arg2);
			this.streamWriter.Write(format, arg0, arg1, arg2);
		}

		/// <summary>
		/// 输出字符串
		/// </summary>
		/// <param name="format">字符串格式</param>
		/// <param name="arg">格式化参数数组</param>
		public override void Write(string format, params object[] arg)
		{
			this.htmlTextWriter.Write(format, arg);
			this.streamWriter.Write(format, arg);
		}

		/// <summary>
		/// 输出字符串
		/// </summary>
		/// <param name="value">要输出的字符串值</param>
		public override void Write(string value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出无符号整形数
		/// </summary>
		/// <param name="value">要输出的无符号整形数值</param>
		public override void Write(uint value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出无符号长整形数
		/// </summary>
		/// <param name="value">要输出的无符号长整形数值</param>
		public override void Write(ulong value)
		{
			this.htmlTextWriter.Write(value);
			this.streamWriter.Write(value);
		}

		/// <summary>
		/// 输出标记属性
		/// </summary>
		/// <param name="name">属性名</param>
		/// <param name="value">属性值</param>
		public override void WriteAttribute(string name, string value)
		{
			this.htmlTextWriter.WriteAttribute(name, value);
			this.streamWriter.Write(" {0}=\"{1}\"", name, value);
		}

		/// <summary>
		/// 输出标记属性
		/// </summary>
		/// <param name="name">属性名</param>
		/// <param name="value">属性值</param>
		/// <param name="fEncode">是否为 HTML 编码</param>
		public override void WriteAttribute(string name, string value, bool fEncode)
		{
			this.htmlTextWriter.WriteAttribute(name, value, fEncode);
			this.streamWriter.Write(" {0}=\"{1}\"", name, this.EncodeAttributeValue(value, fEncode));
		}

		/// <summary>
		/// 输出开始标记，例如：<html
		/// </summary>
		/// <param name="tagName">要输出的开始标记名称</param>
		public override void WriteBeginTag(string tagName)
		{
			this.htmlTextWriter.WriteBeginTag(tagName);
			this.streamWriter.Write("<"+tagName);
		}

		/// <summary>
		/// 输出结束标记，例如：</html>
		/// </summary>
		/// <param name="tagName">要输出的结束标记名称</param>
		public override void WriteEndTag(string tagName)
		{
			this.htmlTextWriter.WriteEndTag(tagName);
			this.streamWriter.Write("</"+tagName+">");
		}

		/// <summary>
		/// 输出开始标记，例如：<body bgcolor="#ffffff">
		/// </summary>
		/// <param name="tagName">要输出的开始标记名称</param>
		public override void WriteFullBeginTag(string tagName)
		{
			this.htmlTextWriter.WriteFullBeginTag(tagName);
			this.streamWriter.Write("<"+tagName);

			this.RenderStyleAttribute();
		}

		/// <summary>
		/// 输出一空行
		/// </summary>
		public override void WriteLine()
		{
			this.htmlTextWriter.WriteLine();
			this.streamWriter.WriteLine();
		}

		/// <summary>
		/// 输出一行布尔值
		/// </summary>
		/// <param name="value">要输出的布尔值</param>
		public override void WriteLine(bool value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行字符
		/// </summary>
		/// <param name="value">要输出的字符</param>
		public override void WriteLine(char value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行字符数组
		/// </summary>
		/// <param name="buffer">要输出的字符数组</param>
		public override void WriteLine(char[] buffer)
		{
			this.htmlTextWriter.WriteLine(buffer);
			this.streamWriter.WriteLine(buffer);
		}

		/// <summary>
		/// 输出一行字符数组
		/// </summary>
		/// <param name="buffer">要输出的字符数组</param>
		/// <param name="index">起始位置</param>
		/// <param name="count">输出个数</param>
		public override void WriteLine(char[] buffer, int index, int count)
		{
			this.htmlTextWriter.WriteLine(buffer, index, count);
			this.streamWriter.WriteLine(buffer, index, count);
		}

		/// <summary>
		/// 输出一行十进制数
		/// </summary>
		/// <param name="value">要输出的十进制数值</param>
		public override void WriteLine(decimal value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行双精度数
		/// </summary>
		/// <param name="value">要输出的双精度数值</param>
		public override void WriteLine(double value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行单精度数
		/// </summary>
		/// <param name="value">要输出的单精度数值</param>
		public override void WriteLine(float value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行整形数
		/// </summary>
		/// <param name="value">要输出的整形数值</param>
		public override void WriteLine(int value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行长整形数
		/// </summary>
		/// <param name="value">要输出的长整形数值</param>
		public override void WriteLine(long value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行 Object
		/// </summary>
		/// <param name="value">要输出的 Object 值</param>
		public override void WriteLine(object value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行文本
		/// </summary>
		/// <param name="format">文本格式</param>
		/// <param name="arg0">格式化参数 0</param>
		public override void WriteLine(string format, object arg0)
		{
			this.htmlTextWriter.WriteLine(format, arg0);
			this.streamWriter.WriteLine(format, arg0);
		}

		/// <summary>
		/// 输出一行文本
		/// </summary>
		/// <param name="format">文本格式</param>
		/// <param name="arg0">格式化参数 0</param>
		/// <param name="arg1">格式化参数 1</param>
		public override void WriteLine(string format, object arg0, object arg1)
		{
			this.htmlTextWriter.WriteLine(format, arg0, arg1);
			this.streamWriter.WriteLine(format, arg0, arg1);
		}

		/// <summary>
		/// 输出一行文本
		/// </summary>
		/// <param name="format">文本格式</param>
		/// <param name="arg0">格式化参数 0</param>
		/// <param name="arg1">格式化参数 1</param>
		/// <param name="arg2">格式化参数 2</param>
		public override void WriteLine(string format, object arg0, object arg1, object arg2)
		{
			this.htmlTextWriter.WriteLine(format, arg0, arg1, arg2);
			this.streamWriter.WriteLine(format, arg0, arg1, arg2);
		}

		/// <summary>
		/// 输出一行文本
		/// </summary>
		/// <param name="format">文本格式</param>
		/// <param name="arg">格式化参数数组</param>
		public override void WriteLine(string format, params object[] arg)
		{
			this.htmlTextWriter.WriteLine(format, arg);
			this.streamWriter.WriteLine(format, arg);
		}

		/// <summary>
		/// 输出一行无符号整形数
		/// </summary>
		/// <param name="value">要输出的无符号整形数值</param>
		public override void WriteLine(uint value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行无符号长整形数
		/// </summary>
		/// <param name="value">要输出的无符号长整形数值</param>
		public override void WriteLine(ulong value)
		{
			this.htmlTextWriter.WriteLine(value);
			this.streamWriter.WriteLine(value);
		}

		/// <summary>
		/// 输出一行字符串
		/// </summary>
		/// <param name="s">要输出的字符串值</param>
		public override void WriteLine(string s)
		{
			this.htmlTextWriter.WriteLine(s);
			this.streamWriter.WriteLine(s);
		}

		/// <summary>
		/// 输出 Style 样式表属性
		/// </summary>
		/// <param name="name">样式表名</param>
		/// <param name="value">字符串值</param>
		public override void WriteStyleAttribute(string name, string value)
		{
			this.htmlTextWriter.WriteStyleAttribute(name, value);
			this.streamWriter.Write(" {0}=\"{1}\"", name, value);
		}

		/// <summary>
		/// 输出 Style 样式表属性
		/// </summary>
		/// <param name="name">样式表名</param>
		/// <param name="value">字符串值</param>
		/// <param name="fEncode">是否为 HTML 编码</param>
		public override void WriteStyleAttribute(string name, string value, bool fEncode)
		{
			this.htmlTextWriter.WriteStyleAttribute (name, value, fEncode);
			this.streamWriter.Write(" {0}=\"{1}\"", name, this.EncodeAttributeValue(value, fEncode));
		}
		#endregion

		/// <summary>
		/// 写出标签属性和样式属性组
		/// </summary>
		private void RenderStyleAttribute()
		{
			// 写出标签属性
			foreach(object key in this.attributes.Keys)
				this.streamWriter.Write(" {0}=\"{1}\"", key.ToString(), this.attributes[key].ToString());

			// 写出标签样式
			if(this.styles.Count>0)
			{
				this.streamWriter.Write(" style=\"");

				foreach(object key in this.styles.Keys)
					this.streamWriter.Write("{0}: {1}; ", key.ToString(), this.styles[key].ToString());

				this.streamWriter.Write("\"");
			}

			// 清除属性和样式
			this.attributes.Clear();
			this.styles.Clear();

			// 写出结束标记
			this.streamWriter.Write(">");
		}
	}
}