using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
using System.Xml;
using TD.SandDock.Rendering;

namespace TD.SandDock
{
	[DefaultEvent("DockingStarted")]
	[Designer(typeof(SandDockManagerDesigner))]
	[ToolboxBitmap(typeof(SandDockManager))]
	public class SandDockManager : Component
	{
		public event EventHandler DockingStarted
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				this.g = (EventHandler)Delegate.Combine(this.g, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				this.g = (EventHandler)Delegate.Remove(this.g, value);
			}
		}

		public event EventHandler DockingFinished
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				this.h = (EventHandler)Delegate.Combine(this.h, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				this.h = (EventHandler)Delegate.Remove(this.h, value);
			}
		}

		public event ShowControlContextMenuEventHandler ShowControlContextMenu
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				this.i = (ShowControlContextMenuEventHandler)Delegate.Combine(this.i, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				this.i = (ShowControlContextMenuEventHandler)Delegate.Remove(this.i, value);
			}
		}

		public event DockControlEventHandler DockControlActivated
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				this.j = (DockControlEventHandler)Delegate.Combine(this.j, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				this.j = (DockControlEventHandler)Delegate.Remove(this.j, value);
			}
		}

		public SandDockManager()
		{
			this.c = new WhidbeyRenderer();
			this.a = new ArrayList();
			this.b = new ArrayList();
		}

		protected internal virtual void OnShowControlContextMenu(ShowControlContextMenuEventArgs e)
		{
			if (this.i != null)
			{
				this.i(this, e);
			}
		}

		internal void a(DockControl A_0)
		{
			if (!this.b.Contains(A_0))
			{
				this.b.Add(A_0);
			}
		}

		internal void b(DockControl A_0)
		{
			if (this.b.Contains(A_0))
			{
				this.b.Remove(A_0);
			}
		}

		internal void c(DockControl A_0)
		{
			if (this.j != null)
			{
				this.j(this, new DockControlEventArgs(A_0));
			}
		}

		[Category("Appearance")]
		[Description("Indicates the type of visual artifacts drawn to the screen to indicate size and position while docking.")]
		[DefaultValue(typeof(DockingHints), "TranslucentFill")]
		public DockingHints DockingHints
		{
			get
			{
				return this.d;
			}
			set
			{
				this.d = value;
			}
		}

		[DefaultValue(typeof(DockingManager), "Standard")]
		[Category("Behavior")]
		[Description("Indicates the method of user interaction during a docking operation.")]
		public DockingManager DockingManager
		{
			get
			{
				return this.e;
			}
			set
			{
				this.e = value;
			}
		}

		public void SetLayout(string layout)
		{
			DockContainer[] array = new DockContainer[checked((uint)this.a.Count)];
			this.a.CopyTo(array);
			ArrayList arrayList = new ArrayList();
			foreach (DockContainer dockContainer in array)
			{
				dockContainer.m();
				if (dockContainer.IsFloating)
				{
					arrayList.Add(dockContainer);
				}
			}
			try
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.LoadXml(layout);
				XmlNode xmlNode = xmlDocument.GetElementsByTagName("Layout")[0];
				foreach (object obj in xmlNode.ChildNodes)
				{
					XmlNode xmlNode2 = (XmlNode)obj;
					if (xmlNode2.NodeType == XmlNodeType.Element && xmlNode2.Name == "Window")
					{
						this.c(xmlNode2);
					}
					else if (xmlNode2.NodeType == XmlNodeType.Element && xmlNode2.Name == "Container" && xmlNode2.HasChildNodes)
					{
						this.b(xmlNode2);
					}
					else if (xmlNode2.NodeType == XmlNodeType.Element && xmlNode2.Name == "FloatingContainer" && xmlNode2.HasChildNodes)
					{
						if (arrayList.Count != 0)
						{
							this.a(xmlNode2, (m)arrayList[0]);
							arrayList.RemoveAt(0);
						}
						else
						{
							this.a(xmlNode2, null);
						}
					}
				}
			}
			catch
			{
				throw new ArgumentException("The layout information provided could not be interpreted.");
			}
			foreach (object obj2 in arrayList)
			{
				m a_ = (m)obj2;
				this.a(a_);
			}
		}

		private void c(XmlNode A_0)
		{
			Guid a_ = new Guid(A_0.Attributes["Guid"].Value);
			DockControl dockControl = this.b(a_);
			if (dockControl != null)
			{
				Size a_2 = (Size)TypeDescriptor.GetConverter(typeof(Size)).ConvertFrom(A_0.Attributes["FloatingSize"].Value);
				Point a_3 = (Point)TypeDescriptor.GetConverter(typeof(Point)).ConvertFrom(A_0.Attributes["FloatingLocation"].Value);
				DockLocation a_4 = (DockLocation)Enum.Parse(typeof(DockLocation), A_0.Attributes["DockLocation"].Value);
				dockControl.a(a_2, a_3, a_4);
			}
		}

		private void a(XmlNode A_0, m A_1)
		{
			Rectangle a_ = (Rectangle)TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertFrom(A_0.Attributes["Bounds"].Value);
			bool a_2 = bool.Parse(A_0.Attributes["Visible"].Value);
			if (A_1 == null)
			{
				A_1 = this.a(((DockContainer)this.a[0]).Font);
			}
			foreach (object obj in A_0.ChildNodes)
			{
				XmlNode xmlNode = (XmlNode)obj;
				if (xmlNode.NodeType == XmlNodeType.Element && xmlNode.Name == "SplitLayoutSystem")
				{
					A_1.LayoutSystem = this.a(xmlNode);
				}
			}
			A_1.a(a_, a_2, false);
		}

		private void b(XmlNode A_0)
		{
			Guid a_ = new Guid(A_0.Attributes["Guid"].Value);
			DockContainer dockContainer = this.a(a_);
			if (dockContainer != null)
			{
				Size size = (Size)TypeDescriptor.GetConverter(typeof(Size)).ConvertFrom(A_0.Attributes["Size"].Value);
				foreach (object obj in A_0.ChildNodes)
				{
					XmlNode xmlNode = (XmlNode)obj;
					if (xmlNode.NodeType == XmlNodeType.Element && xmlNode.Name == "SplitLayoutSystem")
					{
						dockContainer.LayoutSystem = this.a(xmlNode);
						if (dockContainer.Collapsed || dockContainer.Empty)
						{
							dockContainer.b(size);
						}
						else
						{
							dockContainer.Size = size;
						}
					}
				}
			}
		}

		private SplitLayoutSystem a(XmlNode A_0)
		{
			Size size = (Size)TypeDescriptor.GetConverter(typeof(Size)).ConvertFrom(A_0.Attributes["WorkingSize"].Value);
			Orientation splitMode = (Orientation)Enum.Parse(typeof(Orientation), A_0.Attributes["SplitMode"].Value);
			int num = int.Parse(A_0.Attributes["LayoutSystems"].Value);
			LayoutSystemBase[] array = new LayoutSystemBase[checked((uint)num)];
			int num2 = 0;
			foreach (object obj in A_0.ChildNodes)
			{
				XmlNode xmlNode = (XmlNode)obj;
				if (xmlNode.NodeType == XmlNodeType.Element && xmlNode.Name == "SplitLayoutSystem")
				{
					array[num2++] = this.a(xmlNode);
				}
				else if (xmlNode.NodeType == XmlNodeType.Element && xmlNode.Name == "DocumentLayoutSystem")
				{
					array[num2++] = this.a(xmlNode, true);
				}
				else if (xmlNode.NodeType == XmlNodeType.Element && xmlNode.Name == "ControlLayoutSystem")
				{
					array[num2++] = this.a(xmlNode, false);
				}
			}
			return new SplitLayoutSystem(size.Width, size.Height, splitMode, array);
		}

		private ControlLayoutSystem a(XmlNode A_0, bool A_1)
		{
			Size size = (Size)TypeDescriptor.GetConverter(typeof(Size)).ConvertFrom(A_0.Attributes["WorkingSize"].Value);
			bool collapsed = bool.Parse(A_0.Attributes["Collapsed"].Value);
			DockControl selectedControl = null;
			if (A_0.Attributes["SelectedControl"] != null)
			{
				Guid a_ = new Guid(A_0.Attributes["SelectedControl"].Value);
				selectedControl = this.b(a_);
			}
			int num = int.Parse(A_0.Attributes["Controls"].Value);
			int a_2 = 0;
			if (A_0.Attributes["PopupSize"] != null)
			{
				a_2 = int.Parse(A_0.Attributes["PopupSize"].Value);
			}
			DockControl[] array = new DockControl[checked((uint)num)];
			int num2 = 0;
			foreach (object obj in A_0.ChildNodes)
			{
				XmlNode xmlNode = (XmlNode)obj;
				if (xmlNode.NodeType == XmlNodeType.Element && xmlNode.Name == "Controls")
				{
					foreach (object obj2 in xmlNode.ChildNodes)
					{
						XmlNode xmlNode2 = (XmlNode)obj2;
						if (xmlNode2.NodeType == XmlNodeType.Element && xmlNode2.Name == "Control")
						{
							Guid a_3 = new Guid(xmlNode2.Attributes["Guid"].Value);
							DockControl dockControl = this.b(a_3);
							array[num2++] = dockControl;
						}
					}
				}
			}
			ControlLayoutSystem controlLayoutSystem;
			if (A_1)
			{
				controlLayoutSystem = new DocumentLayoutSystem(size.Width, size.Height, array, selectedControl);
			}
			else
			{
				controlLayoutSystem = new ControlLayoutSystem(size.Width, size.Height, array, selectedControl);
			}
			controlLayoutSystem.Collapsed = collapsed;
			controlLayoutSystem.PopupSize = a_2;
			return controlLayoutSystem;
		}

		private DockControl b(Guid A_0)
		{
			foreach (object obj in this.b)
			{
				DockControl dockControl = (DockControl)obj;
				if (dockControl.Guid == A_0)
				{
					return dockControl;
				}
			}
			return null;
		}

		private DockContainer a(Guid A_0)
		{
			foreach (object obj in this.a)
			{
				DockContainer dockContainer = (DockContainer)obj;
				if (dockContainer.Guid == A_0)
				{
					return dockContainer;
				}
			}
			return null;
		}

		private string a(Size A_0)
		{
			return (string)TypeDescriptor.GetConverter(typeof(Size)).ConvertTo(A_0, typeof(string));
		}

		public string GetLayout()
		{
			StringWriter stringWriter = new StringWriter();
			XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
			xmlTextWriter.Formatting = Formatting.Indented;
			xmlTextWriter.WriteStartDocument();
			xmlTextWriter.WriteStartElement("Layout");
			foreach (object obj in this.b)
			{
				DockControl a_ = (DockControl)obj;
				this.a(a_, xmlTextWriter);
			}
			foreach (object obj2 in this.a)
			{
				DockContainer a_2 = (DockContainer)obj2;
				this.a(a_2, xmlTextWriter);
			}
			xmlTextWriter.WriteEndElement();
			xmlTextWriter.WriteEndDocument();
			xmlTextWriter.Flush();
			xmlTextWriter.Close();
			return stringWriter.ToString();
		}

		private void a(DockContainer A_0, XmlTextWriter A_1)
		{
			if (A_0 is m)
			{
				m m = (m)A_0;
				A_1.WriteStartElement("FloatingContainer");
				A_1.WriteAttributeString("Bounds", (string)TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertTo(m.a(), typeof(string)));
				A_1.WriteAttributeString("Visible", m.Visible.ToString());
				this.a(A_0.LayoutSystem, A_1);
				A_1.WriteEndElement();
				return;
			}
			A_1.WriteStartElement("Container");
			A_1.WriteAttributeString("Guid", A_0.Guid.ToString());
			Size size = A_0.Size;
			if (A_0.Collapsed || A_0.Empty)
			{
				if (A_0.Dock == DockStyle.Left || A_0.Dock == DockStyle.Right)
				{
					size.Width = A_0.ContentSize;
				}
				else if (A_0.Dock == DockStyle.Top || A_0.Dock == DockStyle.Bottom)
				{
					size.Height = A_0.ContentSize;
				}
			}
			A_1.WriteAttributeString("Size", this.a(size));
			this.a(A_0.LayoutSystem, A_1);
			A_1.WriteEndElement();
		}

		private void a(LayoutSystemBase A_0, XmlTextWriter A_1)
		{
			if (A_0 is SplitLayoutSystem)
			{
				A_1.WriteStartElement("SplitLayoutSystem");
			}
			else if (A_0 is DocumentLayoutSystem)
			{
				A_1.WriteStartElement("DocumentLayoutSystem");
			}
			else
			{
				if (!(A_0 is ControlLayoutSystem))
				{
					return;
				}
				A_1.WriteStartElement("ControlLayoutSystem");
			}
			A_1.WriteAttributeString("WorkingSize", this.a(new Size((int)A_0.f.Width, (int)A_0.f.Height)));
			if (A_0 is SplitLayoutSystem)
			{
				SplitLayoutSystem splitLayoutSystem = (SplitLayoutSystem)A_0;
				A_1.WriteAttributeString("SplitMode", splitLayoutSystem.SplitMode.ToString());
				A_1.WriteAttributeString("LayoutSystems", splitLayoutSystem.LayoutSystems.Count.ToString());
				using (IEnumerator enumerator = splitLayoutSystem.LayoutSystems.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						object obj = enumerator.Current;
						LayoutSystemBase a_ = (LayoutSystemBase)obj;
						this.a(a_, A_1);
					}
					goto IL_20D;
				}
			}
			if (A_0 is ControlLayoutSystem || A_0 is DocumentLayoutSystem)
			{
				ControlLayoutSystem controlLayoutSystem = (ControlLayoutSystem)A_0;
				A_1.WriteAttributeString("Collapsed", controlLayoutSystem.Collapsed.ToString());
				A_1.WriteAttributeString("Controls", controlLayoutSystem.Controls.Count.ToString());
				if (controlLayoutSystem.SelectedControl != null)
				{
					A_1.WriteAttributeString("SelectedControl", controlLayoutSystem.SelectedControl.Guid.ToString());
				}
				A_1.WriteAttributeString("PopupSize", controlLayoutSystem.PopupSize.ToString());
				A_1.WriteStartElement("Controls");
				foreach (object obj2 in controlLayoutSystem.Controls)
				{
					DockControl dockControl = (DockControl)obj2;
					A_1.WriteStartElement("Control");
					A_1.WriteAttributeString("Guid", dockControl.Guid.ToString());
					A_1.WriteEndElement();
				}
				A_1.WriteEndElement();
			}
			IL_20D:
			A_1.WriteEndElement();
		}

		private void a(DockControl A_0, XmlTextWriter A_1)
		{
			A_1.WriteStartElement("Window");
			A_1.WriteAttributeString("Guid", A_0.Guid.ToString());
			A_1.WriteAttributeString("FloatingSize", this.a(A_0.FloatingSize));
			A_1.WriteAttributeString("FloatingLocation", (string)TypeDescriptor.GetConverter(typeof(Point)).ConvertTo(A_0.FloatingLocation, typeof(string)));
			A_1.WriteAttributeString("DockLocation", A_0.DockLocation.ToString());
			A_1.WriteEndElement();
		}

		[Browsable(false)]
		public Form OwnerForm
		{
			get
			{
				return this.f;
			}
			set
			{
				if (this.f != null && this.f == value)
				{
					return;
				}
				if (this.f != null)
				{
					this.f.Activated -= this.b;
					this.f.Deactivate -= this.a;
				}
				this.f = value;
				if (this.f != null)
				{
					this.f.Activated += this.b;
					this.f.Deactivate += this.a;
				}
			}
		}

		public DockControl[] GetDockControls()
		{
			DockControl[] array = new DockControl[checked((uint)this.b.Count)];
			this.b.CopyTo(array);
			return array;
		}

		[Description("The renderer used to calculate object metrics and draw contents.")]
		[Category("Appearance")]
		public RendererBase Renderer
		{
			get
			{
				return this.c;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException();
				}
				if (this.c != null)
				{
					this.c.Dispose();
				}
				this.c = value;
				this.a();
			}
		}

		private bool ShouldSerializeRenderer()
		{
			return !(this.c is WhidbeyRenderer);
		}

		private void a()
		{
			foreach (object obj in this.a)
			{
				DockContainer dockContainer = (DockContainer)obj;
				dockContainer.o();
			}
		}

		internal void a(DockContainer A_0)
		{
			if (!this.a.Contains(A_0))
			{
				this.a.Add(A_0);
			}
		}

		internal void b(DockContainer A_0)
		{
			if (this.a.Contains(A_0))
			{
				this.a.Remove(A_0);
			}
		}

		internal DockContainer a(DockStyle A_0)
		{
			return this.a(A_0, null);
		}

		internal DockContainer a(DockStyle A_0, Form A_1)
		{
			foreach (object obj in this.a)
			{
				DockContainer dockContainer = (DockContainer)obj;
				if (dockContainer.Dock == A_0 && (A_1 == null || A_1 == dockContainer.FindForm()))
				{
					return dockContainer;
				}
			}
			return null;
		}

		public override ISite Site
		{
			get
			{
				return base.Site;
			}
			set
			{
				base.Site = value;
				if (value != null)
				{
					IDesignerHost designerHost = (IDesignerHost)this.GetService(typeof(IDesignerHost));
					if (designerHost != null && designerHost.RootComponent is Form)
					{
						this.f = (Form)designerHost.RootComponent;
					}
				}
			}
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				DockContainer[] array = new DockContainer[checked((uint)this.a.Count)];
				this.a.CopyTo(array);
				foreach (DockContainer dockContainer in array)
				{
					dockContainer.Dispose();
				}
			}
			base.Dispose(disposing);
		}

		protected internal virtual void OnDockingStarted(EventArgs e)
		{
			if (this.g != null)
			{
				this.g(this, e);
			}
		}

		protected internal virtual void OnDockingFinished(EventArgs e)
		{
			if (this.h != null)
			{
				this.h(this, e);
			}
		}

		private void b(object A_0, EventArgs A_1)
		{
			foreach (object obj in this.a)
			{
				DockContainer dockContainer = (DockContainer)obj;
				if (!dockContainer.IsFloating)
				{
					dockContainer.c(A_0, A_1);
				}
			}
		}

		private void a(object A_0, EventArgs A_1)
		{
			foreach (object obj in this.a)
			{
				DockContainer dockContainer = (DockContainer)obj;
				if (!dockContainer.IsFloating)
				{
					dockContainer.d(A_0, A_1);
				}
			}
		}

		internal m b()
		{
			if (this.a.Count != 0)
			{
				return this.a(((DockContainer)this.a[0]).Font);
			}
			return this.a(Control.DefaultFont);
		}

		private m a(Font A_0)
		{
			m m = new m();
			m.Font = new Font(A_0, A_0.Style);
			m.Manager = this;
			if (this.OwnerForm != null)
			{
				this.OwnerForm.AddOwnedForm(m.l());
			}
			return m;
		}

		internal void a(m A_0)
		{
			A_0.f();
			if (this.OwnerForm != null)
			{
				this.OwnerForm.RemoveOwnedForm(A_0.l());
			}
			A_0.Manager = null;
			A_0.Controls.Clear();
			A_0.Dispose();
		}

		internal ArrayList a;

		internal ArrayList b;

		private RendererBase c;

		private DockingHints d = DockingHints.TranslucentFill;

		private DockingManager e = DockingManager.Standard;

		private Form f;

		private EventHandler g;

		private EventHandler h;

		private ShowControlContextMenuEventHandler i;

		private DockControlEventHandler j;
	}
}
