#region XML LoadSave Routines

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml.Serialization;
#if !PocketPC && !NoGUI
using System.Drawing;
using System.Windows.Forms;
#endif

namespace XMLRoutines
{
	public class XMLSettings
	{
		#region Паблик поля, которые будут сериализоваться в XML

		#endregion
		private class XMLSerializerItem
		{
			public XmlSerializer Serializer;
			public Type SerializerType;
			public override string ToString()
			{
				return SerializerType.Name + (Serializer == null ? " NULL" : "");
			}
		}

		private static readonly List<XMLSerializerItem> Serializers = new List<XMLSerializerItem>();

		static XMLSettings()
		{
			XMLSerializerItem itm = new XMLSerializerItem();
			itm.SerializerType = typeof (XMLSettings);
			itm.Serializer = GetSerializer(itm.SerializerType);
		}

		private static Type[] GetSelfTypes(Type sType)
		{
			Type[] resTypes;
			Type T = sType;
			FieldInfo[] FIs = T.GetFields();
			List<Type> res = new List<Type>();
			foreach (FieldInfo fi in FIs)
			{
				if (!fi.FieldType.IsPrimitive && !res.Contains(fi.FieldType))
					res.Add(fi.FieldType);
			}
			resTypes = res.ToArray();
			return resTypes;
		}

		private static XmlSerializer GetSerializer(Type sType)
		{
			XmlSerializer res = null;
			XMLSerializerItem itm;
			for (int i = 0; i < Serializers.Count; i++)
			{
				itm = Serializers[i];
				if (itm != null)
				{
					if (itm.SerializerType == sType && itm.Serializer != null)
					{
						res = itm.Serializer;
						break;
					}
				}
			}
			if (res == null)
			{
				itm = new XMLSerializerItem();
				itm.SerializerType = sType;
				itm.Serializer = res = new XmlSerializer(sType, GetSelfTypes(sType));
				Serializers.Add(itm);
			}
			return res;
		}

		internal static XMLSettings FromXMLString(string xmlStr, Type sType)
		{
			XMLSettings res = null;
			try
			{
				if (!string.IsNullOrEmpty(xmlStr))
				{
					using (StreamWriter sw = new StreamWriter(new MemoryStream(),Encoding.GetEncoding(1251)))
					{
						sw.Write(xmlStr);
						sw.Flush();
						sw.BaseStream.Position = 0;
						XmlSerializer XML = GetSerializer(sType);
						res = (XMLSettings) XML.Deserialize(sw.BaseStream);
						sw.Close();
					}

				}
			}catch
			{}
			return res;
		}

		protected static XMLSettings LoadSettings(string fName, Type sType)
		{
			if (string.IsNullOrEmpty(fName))
				return null;
			if(!File.Exists(fName))
				return null;
			XMLSettings tmpSetings = null;
			using (FileStream fs = new FileStream(fName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
			{
				try
				{
					XmlSerializer XML = GetSerializer(sType);
					tmpSetings = (XMLSettings) XML.Deserialize(fs);
					fs.Close();
				}
				catch
				{
				}
			}
			return tmpSetings;
		}

		internal string ToXMLString()
		{
			string res = null;
			try
			{
				XmlSerializer XML = GetSerializer(this.GetType());
				using (MemoryStream ms = new MemoryStream())
				{
					XML.Serialize(ms, this);
					ms.Position = 0;
					res = new StreamReader(ms,Encoding.GetEncoding(1251)).ReadToEnd();
					ms.Close();
				}
			}
			catch
			{ }
			return res;
		}
		protected bool SaveSettings(string fName)
		{
			bool res = true;
			if (string.IsNullOrEmpty(fName))
				return false;
			using (FileStream fs = new FileStream(fName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
			{
				try
				{
					XmlSerializer XML = GetSerializer(this.GetType());
					XML.Serialize(fs, this);
					fs.Close();
				}
				catch
				{
					res = false;
				}
			}
			return res;
		}
	}

	#region Windows Form Settings Routines
#if !PocketPC && !NoGUI
	public class UniversalFormSettings : XMLSettings
	{
		public Point Location;
		public Point RestoreLocation;
		public Size RestoreSize;
		public Size Size;
		public FormWindowState WinState;
		public string DockLayout;

		public void SetToForm(Form F)
		{
			F.WindowState = WinState;
			F.Location = Location;
			F.Size = Size;
		}
		public void GetFromForm(Form F)
		{
			WinState = F.WindowState;
			Location = F.Location;
			Size = F.Size;
			if (WinState != FormWindowState.Normal)
			{
				Location = F.RestoreBounds.Location;
				Size = F.RestoreBounds.Size;
			}			
		}

		public void Save(string FName)
		{
			SaveSettings(FName);
		}
		public static UniversalFormSettings Load(string FName)
		{
			return (UniversalFormSettings)LoadSettings(FName, typeof(UniversalFormSettings));
		}
	}
#endif
	#endregion
}
#endregion
