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

namespace TD.SandDock
{
	[TypeConverter(typeof(SplitLayoutSystemConverter))]
	public class SplitLayoutSystem : LayoutSystemBase
	{
		internal event EventHandler LayoutSystemsChanged
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				this.f = (EventHandler)Delegate.Combine(this.f, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				this.f = (EventHandler)Delegate.Remove(this.f, value);
			}
		}

		public SplitLayoutSystem()
		{
			this.b = new SplitLayoutSystem.LayoutSystemBaseCollection(this);
			this.d = new ArrayList();
		}

		public SplitLayoutSystem(int desiredWidth, int desiredHeight) : this()
		{
			this.f = new SizeF((float)desiredWidth, (float)desiredHeight);
		}

		public SplitLayoutSystem(int desiredWidth, int desiredHeight, Orientation splitMode, LayoutSystemBase[] layoutSystems) : this(desiredWidth, desiredHeight)
		{
			this.c = splitMode;
			this.b.AddRange(layoutSystems);
		}

		public bool Optimize()
		{
			if (this.LayoutSystems.Count != 1 || !(this.LayoutSystems[0] is SplitLayoutSystem))
			{
				foreach (object obj in this.LayoutSystems)
				{
					LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
					if (layoutSystemBase is SplitLayoutSystem)
					{
						SplitLayoutSystem splitLayoutSystem = (SplitLayoutSystem)layoutSystemBase;
						if (splitLayoutSystem.SplitMode == this.SplitMode)
						{
							LayoutSystemBase[] array = new LayoutSystemBase[checked((uint)splitLayoutSystem.LayoutSystems.Count)];
							splitLayoutSystem.LayoutSystems.CopyTo(array, 0);
							splitLayoutSystem.LayoutSystems.b = true;
							splitLayoutSystem.LayoutSystems.Clear();
							int index = this.LayoutSystems.IndexOf(splitLayoutSystem);
							this.LayoutSystems.b = true;
							this.LayoutSystems.Remove(splitLayoutSystem);
							splitLayoutSystem.Dispose();
							for (int i = array.Length - 1; i >= 0; i--)
							{
								this.LayoutSystems.Insert(index, array[i]);
							}
							this.LayoutSystems.b = false;
							return true;
						}
						bool flag = splitLayoutSystem.Optimize();
						if (flag)
						{
							return true;
						}
					}
				}
				return false;
			}
			SplitLayoutSystem splitLayoutSystem2 = (SplitLayoutSystem)this.LayoutSystems[0];
			if (splitLayoutSystem2.LayoutSystems.Count == 1 && splitLayoutSystem2.LayoutSystems[0] is SplitLayoutSystem && ((SplitLayoutSystem)splitLayoutSystem2.LayoutSystems[0]).SplitMode == this.SplitMode)
			{
				SplitLayoutSystem splitLayoutSystem3 = (SplitLayoutSystem)splitLayoutSystem2.LayoutSystems[0];
				LayoutSystemBase[] array2 = new LayoutSystemBase[checked((uint)splitLayoutSystem3.LayoutSystems.Count)];
				splitLayoutSystem3.LayoutSystems.CopyTo(array2, 0);
				splitLayoutSystem3.LayoutSystems.b = true;
				splitLayoutSystem3.LayoutSystems.Clear();
				this.LayoutSystems.b = true;
				this.LayoutSystems.Clear();
				splitLayoutSystem2.Dispose();
				this.LayoutSystems.AddRange(array2);
				this.LayoutSystems.b = false;
				return true;
			}
			return false;
		}

		internal override void OnDockingManagerCommitted(j.b target)
		{
			base.OnDockingManagerCommitted(target);
			if (target == null || target.a == j.c.b || target.a == j.c.g)
			{
				return;
			}
			m m = (m)base.DockContainer;
			SandDockManager manager = base.DockContainer.Manager;
			if (target.a == j.c.c)
			{
				m.a(target.e, true, true);
				return;
			}
			this.f = base.Bounds.Size;
			m.LayoutSystem = new SplitLayoutSystem();
			manager.a(m);
			if (target.a == j.c.f)
			{
				if (target.b.Empty)
				{
					target.b.LayoutSystem.LayoutSystems.Add(this);
					return;
				}
				target.b.b(this);
				return;
			}
			else
			{
				if (target.a == j.c.e)
				{
					this.MoveToLayoutSystem(target.c, target.f);
					return;
				}
				if (target.a == j.c.d)
				{
					if (this.LayoutSystems.Count == 1 && this.LayoutSystems[0] is ControlLayoutSystem)
					{
						ControlLayoutSystem layoutSystem = (ControlLayoutSystem)this.LayoutSystems[0];
						this.LayoutSystems.Remove(layoutSystem);
						target.c.SplitForLayoutSystem(layoutSystem, target.d);
						return;
					}
					target.c.SplitForLayoutSystem(this, target.d);
				}
				return;
			}
		}

		public void MoveToLayoutSystem(ControlLayoutSystem layoutSystem)
		{
			this.MoveToLayoutSystem(layoutSystem, 0);
		}

		public void MoveToLayoutSystem(ControlLayoutSystem layoutSystem, int index)
		{
			DockControl dockControl = null;
			if (this.LayoutSystems.Count == 1 && this.LayoutSystems[0] is ControlLayoutSystem)
			{
				dockControl = ((ControlLayoutSystem)this.LayoutSystems[0]).SelectedControl;
			}
			ArrayList arrayList = new ArrayList();
			this.a(this, arrayList);
			foreach (object obj in arrayList)
			{
				DockControl dockControl2 = (DockControl)obj;
				dockControl2.b.Controls.Remove(dockControl2);
			}
			foreach (object obj2 in arrayList)
			{
				DockControl control = (DockControl)obj2;
				layoutSystem.Controls.Insert(index, control);
			}
			if (dockControl != null)
			{
				layoutSystem.SelectedControl = dockControl;
			}
		}

		private new void a(SplitLayoutSystem A_0, ArrayList A_1)
		{
			foreach (object obj in A_0.b)
			{
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
				if (layoutSystemBase is SplitLayoutSystem)
				{
					this.a((SplitLayoutSystem)layoutSystemBase, A_1);
				}
				else if (layoutSystemBase is ControlLayoutSystem)
				{
					foreach (object obj2 in ((ControlLayoutSystem)layoutSystemBase).Controls)
					{
						DockControl value = (DockControl)obj2;
						A_1.Add(value);
					}
				}
			}
		}

		internal new void a(Point A_0, out LayoutSystemBase A_1, out LayoutSystemBase A_2)
		{
			int num = 0;
			foreach (object obj in this.LayoutSystems)
			{
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
				if (this.SplitMode == Orientation.Horizontal)
				{
					if (A_0.Y >= layoutSystemBase.Bounds.Bottom && A_0.Y <= layoutSystemBase.Bounds.Bottom + 4)
					{
						num = this.LayoutSystems.IndexOf(layoutSystemBase);
						break;
					}
				}
				else if (A_0.X >= layoutSystemBase.Bounds.Right && A_0.X <= layoutSystemBase.Bounds.Right + 4)
				{
					num = this.LayoutSystems.IndexOf(layoutSystemBase);
					break;
				}
			}
			A_1 = this.LayoutSystems[num];
			A_2 = this.LayoutSystems[num + 1];
		}

		protected internal override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			foreach (object obj in this.d)
			{
				Rectangle rectangle = (Rectangle)obj;
				if (rectangle.Contains(e.X, e.Y))
				{
					LayoutSystemBase a_;
					LayoutSystemBase a_2;
					this.a(new Point(e.X, e.Y), out a_, out a_2);
					if (this.e != null)
					{
						this.e.b();
					}
					DockingHints a_3 = (base.DockContainer.Manager != null) ? base.DockContainer.Manager.DockingHints : base.DockContainer.DockingHints;
					this.e = new q(base.DockContainer, this, a_, a_2, new Point(e.X, e.Y), a_3);
					this.e.a(new EventHandler(this.a));
					this.e.b(new q.a(this.a));
					break;
				}
			}
		}

		protected internal override void OnMouseUp(MouseEventArgs e)
		{
			base.OnMouseUp(e);
			if (this.g != null)
			{
				this.g.a();
				return;
			}
			if (this.e != null)
			{
				this.e.a();
				return;
			}
		}

		internal new bool a(int A_0, int A_1)
		{
			foreach (object obj in this.d)
			{
				Rectangle rectangle = (Rectangle)obj;
				if (rectangle.Contains(A_0, A_1))
				{
					return true;
				}
			}
			return false;
		}

		protected internal override void OnMouseMove(MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left)
			{
				if (this.g != null)
				{
					this.g.a(Cursor.Position);
					return;
				}
				if (this.e != null)
				{
					this.e.a(new Point(e.X, e.Y));
					return;
				}
			}
			bool flag = this.a(e.X, e.Y);
			if (flag)
			{
				if (this.c == Orientation.Horizontal)
				{
					base.DockContainer.Cursor = Cursors.HSplit;
				}
				else
				{
					base.DockContainer.Cursor = Cursors.VSplit;
				}
			}
			else
			{
				base.DockContainer.Cursor = Cursors.Default;
			}
			base.OnMouseMove(e);
		}

		[Description("Indicates whether this layout is split horizontally or vertically.")]
		[Category("Layout")]
		[DefaultValue(typeof(Orientation), "Horizontal")]
		public Orientation SplitMode
		{
			get
			{
				return this.c;
			}
			set
			{
				this.c = value;
				this.c();
			}
		}

		internal new void b()
		{
			if (base.DockContainer != null)
			{
				base.DockContainer.LayoutSystemsChanged();
			}
			if (this.f != null)
			{
				this.f(this, EventArgs.Empty);
			}
		}

		internal new void c()
		{
			if (base.DockContainer != null)
			{
				base.DockContainer.a(this, base.Bounds);
			}
			if (base.DockContainer != null)
			{
				base.DockContainer.Invalidate(base.Bounds);
			}
		}

		internal override void SetDockContainer(DockContainer dockContainer)
		{
			base.SetDockContainer(dockContainer);
			foreach (object obj in this.LayoutSystems)
			{
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
				layoutSystemBase.SetDockContainer(dockContainer);
			}
		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public SplitLayoutSystem.LayoutSystemBaseCollection LayoutSystems
		{
			get
			{
				return this.b;
			}
		}

		internal new void a(ControlLayoutSystem A_0)
		{
			int num;
			LayoutSystemBase[] array = this.a(out num);
			float num2 = 0f;
			for (int i = 0; i < num; i++)
			{
				LayoutSystemBase layoutSystemBase = array[i];
				if (layoutSystemBase != A_0)
				{
					if (this.c == Orientation.Horizontal)
					{
						num2 += layoutSystemBase.f.Height;
					}
					else
					{
						num2 += layoutSystemBase.f.Width;
					}
				}
			}
			float num3 = (this.c == Orientation.Horizontal) ? A_0.f.Height : A_0.f.Width;
			float num4 = (float)((this.c == Orientation.Horizontal) ? (base.Bounds.Height - (num - 1) * 4) : (base.Bounds.Width - (num - 1) * 4));
			if (num3 > num4 * 0.75f)
			{
				num3 = num4 * 0.75f;
			}
			for (int j = 0; j < num; j++)
			{
				if (array[j] != A_0)
				{
					if (this.c == Orientation.Horizontal)
					{
						LayoutSystemBase layoutSystemBase2 = array[j];
						layoutSystemBase2.f.Height = layoutSystemBase2.f.Height - num3 * (array[j].f.Height / num2);
					}
					else
					{
						LayoutSystemBase layoutSystemBase3 = array[j];
						layoutSystemBase3.f.Width = layoutSystemBase3.f.Width - num3 * (array[j].f.Width / num2);
					}
				}
			}
		}

		private new LayoutSystemBase[] a(out int A_0)
		{
			A_0 = 0;
			LayoutSystemBase[] array = new LayoutSystemBase[checked((uint)this.LayoutSystems.Count)];
			foreach (object obj in this.LayoutSystems)
			{
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
				if (layoutSystemBase is ControlLayoutSystem)
				{
					ControlLayoutSystem controlLayoutSystem = (ControlLayoutSystem)layoutSystemBase;
					if (!controlLayoutSystem.Collapsed || (base.IsInContainer && !base.DockContainer.CanShowCollapsed))
					{
						array[A_0++] = layoutSystemBase;
					}
				}
				else if (layoutSystemBase is SplitLayoutSystem)
				{
					SplitLayoutSystem splitLayoutSystem = (SplitLayoutSystem)layoutSystemBase;
					if (splitLayoutSystem.d())
					{
						array[A_0++] = layoutSystemBase;
					}
				}
			}
			return array;
		}

		protected internal override void Layout(RendererBase renderer, Graphics graphics, Rectangle bounds, bool floating)
		{
			base.Layout(renderer, graphics, bounds, floating);
			int num;
			LayoutSystemBase[] array = this.a(out num);
			if (num == 0)
			{
				return;
			}
			if (num > 1)
			{
				floating = false;
			}
			for (int i = 0; i < num; i++)
			{
				if (this.c == Orientation.Horizontal)
				{
					if (array[i].f.Height <= 0f)
					{
						array[i].f.Height = 400f;
					}
					array[i].f.Width = (float)bounds.Width;
				}
				if (this.c == Orientation.Vertical)
				{
					if (array[i].f.Width <= 0f)
					{
						array[i].f.Width = 250f;
					}
					array[i].f.Height = (float)bounds.Height;
				}
			}
			int num2 = (this.c == Orientation.Horizontal) ? (bounds.Height - (num - 1) * 4) : (bounds.Width - (num - 1) * 4);
			float num3 = 0f;
			for (int j = 0; j < num; j++)
			{
				num3 += ((this.c == Orientation.Horizontal) ? array[j].f.Height : array[j].f.Width);
			}
			this.d.Clear();
			if (num2 > 0)
			{
				if ((float)num2 != num3)
				{
					float num4 = (float)num2 - num3;
					for (int k = 0; k < num; k++)
					{
						if (this.c == Orientation.Horizontal)
						{
							LayoutSystemBase layoutSystemBase = array[k];
							layoutSystemBase.f.Height = layoutSystemBase.f.Height + num4 * (array[k].f.Height / num3);
						}
						else
						{
							LayoutSystemBase layoutSystemBase2 = array[k];
							layoutSystemBase2.f.Width = layoutSystemBase2.f.Width + num4 * (array[k].f.Width / num3);
						}
					}
					num3 = 0f;
					for (int l = 0; l < num; l++)
					{
						num3 += ((this.c == Orientation.Horizontal) ? array[l].f.Height : array[l].f.Width);
					}
					num4 = (float)num2 - num3;
					if (this.c == Orientation.Horizontal)
					{
						LayoutSystemBase layoutSystemBase3 = array[0];
						layoutSystemBase3.f.Height = layoutSystemBase3.f.Height + num4;
					}
					else
					{
						LayoutSystemBase layoutSystemBase4 = array[0];
						layoutSystemBase4.f.Width = layoutSystemBase4.f.Width + num4;
					}
				}
				int num5 = (this.c == Orientation.Horizontal) ? bounds.Y : bounds.X;
				for (int m = 0; m < num; m++)
				{
					if (this.c == Orientation.Horizontal)
					{
						int num6 = Convert.ToInt32(array[m].f.Height);
						if (m == num - 1)
						{
							num6 = bounds.Bottom - num5;
						}
						array[m].Layout(renderer, graphics, new Rectangle(bounds.X, num5, bounds.Width, num6), floating);
						num5 += num6 + 4;
					}
					else
					{
						int num7 = Convert.ToInt32(array[m].f.Width);
						if (m == num - 1)
						{
							num7 = bounds.Right - num5;
						}
						array[m].Layout(renderer, graphics, new Rectangle(num5, bounds.Y, num7, bounds.Height), floating);
						num5 += num7 + 4;
					}
				}
				for (int n = 0; n < num - 1; n++)
				{
					bounds = array[n].Bounds;
					if (this.c == Orientation.Horizontal)
					{
						bounds.Offset(0, bounds.Height);
						bounds.Height = 4;
					}
					else
					{
						bounds.Offset(bounds.Width, 0);
						bounds.Width = 4;
					}
					this.d.Add(bounds);
				}
			}
		}

		internal override void Paint(RendererBase renderer, Graphics graphics, Font font)
		{
			foreach (object obj in this.d)
			{
				Rectangle bounds = (Rectangle)obj;
				renderer.DrawSplitter(graphics, bounds, this.c);
			}
			foreach (object obj2 in this.LayoutSystems)
			{
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj2;
				if (!(layoutSystemBase is ControlLayoutSystem) || !((ControlLayoutSystem)layoutSystemBase).Collapsed || !base.DockContainer.CanShowCollapsed)
				{
					Region clip = graphics.Clip;
					graphics.SetClip(layoutSystemBase.Bounds);
					layoutSystemBase.Paint(renderer, graphics, font);
					graphics.Clip = clip;
				}
			}
		}

		private new void a()
		{
			this.e.b(new EventHandler(this.a));
			this.e.a(new q.a(this.a));
			this.e = null;
		}

		private new void a(object A_0, EventArgs A_1)
		{
			this.a();
		}

		private new void a(LayoutSystemBase A_0, LayoutSystemBase A_1, int A_2, int A_3)
		{
			this.a();
			if (this.SplitMode == Orientation.Horizontal)
			{
				A_0.f.Height = (float)A_2;
				A_1.f.Height = (float)A_3;
			}
			else
			{
				A_0.f.Width = (float)A_2;
				A_1.f.Width = (float)A_3;
			}
			this.c();
		}

		internal bool d()
		{
			foreach (object obj in this.b)
			{
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
				if (layoutSystemBase is ControlLayoutSystem)
				{
					ControlLayoutSystem controlLayoutSystem = (ControlLayoutSystem)layoutSystemBase;
					if (!controlLayoutSystem.Collapsed || (base.IsInContainer && !base.DockContainer.CanShowCollapsed))
					{
						return true;
					}
				}
				else if (((SplitLayoutSystem)layoutSystemBase).d())
				{
					return true;
				}
			}
			return false;
		}

		public override void Dispose()
		{
			LayoutSystemBase[] array = new LayoutSystemBase[checked((uint)this.LayoutSystems.Count)];
			this.LayoutSystems.CopyTo(array, 0);
			this.LayoutSystems.Clear();
			foreach (LayoutSystemBase layoutSystemBase in array)
			{
				layoutSystemBase.Dispose();
			}
			base.Dispose();
		}

		internal new const int a = 4;

		private new SplitLayoutSystem.LayoutSystemBaseCollection b = null;

		private new Orientation c = Orientation.Horizontal;

		private ArrayList d = null;

		private q e = null;

		private new EventHandler f;

		public class LayoutSystemBaseCollection : CollectionBase
		{
			internal LayoutSystemBaseCollection(SplitLayoutSystem A_0)
			{
				this.a = A_0;
			}

			private void a()
			{
				this.a.b();
			}

			protected override void OnClear()
			{
				base.OnClear();
				foreach (object obj in this)
				{
					LayoutSystemBase layoutSystemBase = (LayoutSystemBase)obj;
					layoutSystemBase.c = null;
					layoutSystemBase.SetDockContainer(null);
				}
			}

			protected override void OnClearComplete()
			{
				base.OnClearComplete();
				if (!this.b)
				{
					this.a();
				}
			}

			protected override void OnInsertComplete(int index, object value)
			{
				base.OnInsertComplete(index, value);
				LayoutSystemBase layoutSystemBase = (LayoutSystemBase)value;
				layoutSystemBase.c = this.a;
				layoutSystemBase.SetDockContainer(this.a.DockContainer);
				if (this.a.c == null && this.a.DockContainer != null)
				{
					int num = (layoutSystemBase.f.Width < layoutSystemBase.f.Height) ? ((int)layoutSystemBase.f.Width) : ((int)layoutSystemBase.f.Height);
					this.a.DockContainer.b(new Size(num, num));
				}
				if (!this.b)
				{
					this.a();
				}
			}

			protected override void OnRemoveComplete(int index, object value)
			{
				base.OnRemoveComplete(index, value);
				((LayoutSystemBase)value).c = null;
				((LayoutSystemBase)value).SetDockContainer(null);
				if (!this.b)
				{
					if (base.Count <= 1 && this.a.c != null)
					{
						SplitLayoutSystem splitLayoutSystem = (SplitLayoutSystem)this.a.c;
						if (base.Count == 1)
						{
							LayoutSystemBase layoutSystem = this[0];
							this.b = true;
							this.Remove(layoutSystem);
							this.b = false;
							splitLayoutSystem.LayoutSystems.b = true;
							int index2 = splitLayoutSystem.LayoutSystems.IndexOf(this.a);
							splitLayoutSystem.LayoutSystems.Remove(this.a);
							splitLayoutSystem.LayoutSystems.Insert(index2, layoutSystem);
							splitLayoutSystem.LayoutSystems.b = false;
							splitLayoutSystem.b();
							return;
						}
						if (base.Count == 0)
						{
							splitLayoutSystem.LayoutSystems.Remove(this.a);
							return;
						}
					}
					else
					{
						this.a();
					}
				}
			}

			public void AddRange(LayoutSystemBase[] layoutSystems)
			{
				this.b = true;
				foreach (LayoutSystemBase layoutSystem in layoutSystems)
				{
					this.Add(layoutSystem);
				}
				this.b = false;
				this.a();
			}

			public int Add(LayoutSystemBase layoutSystem)
			{
				int count = base.Count;
				this.Insert(count, layoutSystem);
				return count;
			}

			public void Insert(int index, LayoutSystemBase layoutSystem)
			{
				if (layoutSystem.c != null)
				{
					throw new ArgumentException("Layout system already has a parent. You must first remove it from its parent.");
				}
				base.List.Insert(index, layoutSystem);
			}

			public LayoutSystemBase this[int index]
			{
				get
				{
					return (LayoutSystemBase)base.List[index];
				}
			}

			public void Remove(LayoutSystemBase layoutSystem)
			{
				base.List.Remove(layoutSystem);
			}

			public bool Contains(LayoutSystemBase layoutSystem)
			{
				return base.List.Contains(layoutSystem);
			}

			public int IndexOf(LayoutSystemBase layoutSystem)
			{
				return base.List.IndexOf(layoutSystem);
			}

			public void CopyTo(LayoutSystemBase[] array, int index)
			{
				base.List.CopyTo(array, index);
			}

			private SplitLayoutSystem a = null;

			internal bool b = false;
		}
	}
}
