using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace SyncMany
{
	public static class ObjectSerializer<T> where T : class
	{
		public static string StringSerialize(T t)
		{
			string strOutput = string.Empty;
			XmlSerializer xs = new XmlSerializer(typeof(T));
			using (MemoryStream ms = new MemoryStream())
			{
				xs.Serialize(new NonXsiTextWriter(ms, Encoding.UTF8), t);
				//xs.Serialize(ms, t);
				ms.Position = 0;
				StreamReader sr = new StreamReader(ms);
				strOutput = sr.ReadToEnd();
				ms.Close();
			}
			return strOutput;
		}
		public static T StringDeserialize(string s)
		{
			T t;
			XmlSerializer xs = new XmlSerializer(typeof(T));
			UTF8Encoding enc = new UTF8Encoding();
			Byte[] arrBytData = enc.GetBytes(s);
			using (MemoryStream ms = new MemoryStream(arrBytData))
			{
				t = (T)xs.Deserialize(ms);
			}
			return t;
		}
		public static void WriteFile(T t, string fileName)
		{
			string strOutput = string.Empty;
			XmlSerializer xs = new XmlSerializer(typeof(T));
			using (FileStream fs = new FileStream(fileName, FileMode.Create))
			{
				xs.Serialize(new NonXsiTextWriter(fs, Encoding.UTF8), t);
				fs.Close();
			}
		}
		public static T ReadFile(string fileName)
		{
			T t;
			XmlSerializer xs = new XmlSerializer(typeof(T));
			using (FileStream fs = new FileStream(fileName, FileMode.Open))
			{
				t = (T)xs.Deserialize(fs);
			}
			return t;
		}
	}
	public class NonXsiTextWriter : XmlTextWriter
	{
		public NonXsiTextWriter(TextWriter w) : base(w) { }
		public NonXsiTextWriter(Stream w, Encoding encoding)
			: base(w, encoding)
		{
			this.Formatting = Formatting.Indented;
		}
		public NonXsiTextWriter(string filename, Encoding encoding) : base(filename, encoding) { }
		bool _skip = false;
		public override void WriteStartAttribute(string prefix, string localName, string ns)
		{
			if ((prefix == "xmlns" && (localName == "xsd" || localName == "xsi")) || // Omits XSD and XSI declarations. 
				ns == XmlSchema.InstanceNamespace) // Omits all XSI attributes. 
			{
				_skip = true;
				return;
			}
			if (localName == "xlink_href")
				base.WriteStartAttribute(prefix, "xlink:href", ns);
			else
				base.WriteStartAttribute(prefix, localName, ns);
		}
		public override void WriteString(string text)
		{
			if (_skip) return;
			base.WriteString(text);
		}
		public override void WriteEndAttribute()
		{
			if (_skip)
			{ // Reset the flag, so we keep writing. 
				_skip = false;
				return;
			}
			base.WriteEndAttribute();
		}
	}
}
