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
	{
		public class LayoutSystemBaseCollection : CollectionBase
		{
			private SplitLayoutSystem m_a = null;

			internal bool b = false;

			public LayoutSystemBase this[int index] => (LayoutSystemBase)base.List[index];

			internal LayoutSystemBaseCollection(SplitLayoutSystem A_0)
			{
				this.m_a = A_0;
			}

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

			protected override void OnClear()
			{
				base.OnClear();
				IEnumerator enumerator = GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						LayoutSystemBase layoutSystemBase = (LayoutSystemBase)enumerator.Current;
						layoutSystemBase.c = null;
						layoutSystemBase.SetDockContainer(null);
					}
				}
				finally
				{
					IDisposable disposable = enumerator as IDisposable;
					if (disposable != null)
					{
						disposable.Dispose();
					}
				}
			}

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

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

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

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

			public int Add(LayoutSystemBase layoutSystem)
			{
				int count = base.Count;
				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 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);
			}
		}

		internal new const int a = 4;

		private new LayoutSystemBaseCollection m_b = null;

		private new Orientation m_c = Orientation.Horizontal;

		private ArrayList m_d = null;

		private q e = null;

		private new EventHandler f;

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

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public LayoutSystemBaseCollection LayoutSystems => this.m_b;

		internal event EventHandler LayoutSystemsChanged
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				f = (EventHandler)Delegate.Combine(f, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				f = (EventHandler)Delegate.Remove(f, value);
			}
		}

		public SplitLayoutSystem()
		{
			this.m_b = new LayoutSystemBaseCollection(this);
			this.m_d = new ArrayList();
		}

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

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

		public bool Optimize()
		{
			if (LayoutSystems.Count == 1 && LayoutSystems[0] is SplitLayoutSystem)
			{
				SplitLayoutSystem splitLayoutSystem = (SplitLayoutSystem)LayoutSystems[0];
				if (splitLayoutSystem.LayoutSystems.Count == 1 && splitLayoutSystem.LayoutSystems[0] is SplitLayoutSystem && ((SplitLayoutSystem)splitLayoutSystem.LayoutSystems[0]).SplitMode == SplitMode)
				{
					SplitLayoutSystem splitLayoutSystem2 = (SplitLayoutSystem)splitLayoutSystem.LayoutSystems[0];
					LayoutSystemBase[] array = new LayoutSystemBase[checked((uint)splitLayoutSystem2.LayoutSystems.Count)];
					splitLayoutSystem2.LayoutSystems.CopyTo(array, 0);
					splitLayoutSystem2.LayoutSystems.b = true;
					splitLayoutSystem2.LayoutSystems.Clear();
					LayoutSystems.b = true;
					LayoutSystems.Clear();
					splitLayoutSystem.Dispose();
					LayoutSystems.AddRange(array);
					LayoutSystems.b = false;
					return true;
				}
			}
			else
			{
				foreach (LayoutSystemBase layoutSystem in LayoutSystems)
				{
					if (!(layoutSystem is SplitLayoutSystem))
					{
						continue;
					}
					SplitLayoutSystem splitLayoutSystem3 = (SplitLayoutSystem)layoutSystem;
					if (splitLayoutSystem3.SplitMode == SplitMode)
					{
						LayoutSystemBase[] array2 = new LayoutSystemBase[checked((uint)splitLayoutSystem3.LayoutSystems.Count)];
						splitLayoutSystem3.LayoutSystems.CopyTo(array2, 0);
						splitLayoutSystem3.LayoutSystems.b = true;
						splitLayoutSystem3.LayoutSystems.Clear();
						int index = LayoutSystems.IndexOf(splitLayoutSystem3);
						LayoutSystems.b = true;
						LayoutSystems.Remove(splitLayoutSystem3);
						splitLayoutSystem3.Dispose();
						for (int num = array2.Length - 1; num >= 0; num--)
						{
							LayoutSystems.Insert(index, array2[num]);
						}
						LayoutSystems.b = false;
						return true;
					}
					if (splitLayoutSystem3.Optimize())
					{
						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 m2 = (m)base.DockContainer;
			SandDockManager manager = base.DockContainer.Manager;
			if (target.a == j.c.c)
			{
				m2.a(target.e, A_1: true, A_2: true);
				return;
			}
			base.f = base.Bounds.Size;
			m2.LayoutSystem = new SplitLayoutSystem();
			manager.a(m2);
			if (target.a == j.c.f)
			{
				if (target.b.Empty)
				{
					target.b.LayoutSystem.LayoutSystems.Add(this);
				}
				else
				{
					target.b.b((LayoutSystemBase)this);
				}
			}
			else if (target.a == j.c.e)
			{
				MoveToLayoutSystem(target.c, target.f);
			}
			else if (target.a == j.c.d)
			{
				if (LayoutSystems.Count == 1 && LayoutSystems[0] is ControlLayoutSystem)
				{
					ControlLayoutSystem layoutSystem = (ControlLayoutSystem)LayoutSystems[0];
					LayoutSystems.Remove(layoutSystem);
					target.c.SplitForLayoutSystem(layoutSystem, target.d);
				}
				else
				{
					target.c.SplitForLayoutSystem(this, target.d);
				}
			}
		}

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

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

		private new void a(SplitLayoutSystem A_0, ArrayList A_1)
		{
			foreach (LayoutSystemBase item in A_0.m_b)
			{
				if (item is SplitLayoutSystem)
				{
					a((SplitLayoutSystem)item, A_1);
				}
				else
				{
					if (!(item is ControlLayoutSystem))
					{
						continue;
					}
					foreach (DockControl control in ((ControlLayoutSystem)item).Controls)
					{
						A_1.Add(control);
					}
				}
			}
		}

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

		protected internal override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			foreach (object item in this.m_d)
			{
				Rectangle rectangle = (Rectangle)item;
				if (rectangle.Contains(e.X, e.Y))
				{
					a(new Point(e.X, e.Y), out var A_, out var A_2);
					if (this.e != null)
					{
						this.e.b();
					}
					DockingHints a_ = ((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_);
					this.e.a((EventHandler)a);
					this.e.b((q.a)a);
					break;
				}
			}
		}

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

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

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

		internal new void b()
		{
			if (base.DockContainer != null)
			{
				base.DockContainer.LayoutSystemsChanged();
			}
			if (f != null)
			{
				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 (LayoutSystemBase layoutSystem in LayoutSystems)
			{
				layoutSystem.SetDockContainer(dockContainer);
			}
		}

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

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

		protected internal override void Layout(RendererBase renderer, Graphics graphics, Rectangle bounds, bool floating)
		{
			base.Layout(renderer, graphics, bounds, floating);
			int A_;
			LayoutSystemBase[] array = a(out A_);
			if (A_ == 0)
			{
				return;
			}
			if (A_ > 1)
			{
				floating = false;
			}
			for (int num = 0; num < A_; num++)
			{
				if (this.m_c == Orientation.Horizontal)
				{
					if (array[num].f.Height <= 0f)
					{
						array[num].f.Height = 400f;
					}
					array[num].f.Width = bounds.Width;
				}
				if (this.m_c == Orientation.Vertical)
				{
					if (array[num].f.Width <= 0f)
					{
						array[num].f.Width = 250f;
					}
					array[num].f.Height = bounds.Height;
				}
			}
			int num2 = ((this.m_c == Orientation.Horizontal) ? (bounds.Height - (A_ - 1) * 4) : (bounds.Width - (A_ - 1) * 4));
			float num3 = 0f;
			for (int num4 = 0; num4 < A_; num4++)
			{
				num3 += ((this.m_c == Orientation.Horizontal) ? array[num4].f.Height : array[num4].f.Width);
			}
			this.m_d.Clear();
			if (num2 <= 0)
			{
				return;
			}
			if ((float)num2 != num3)
			{
				float num5 = (float)num2 - num3;
				for (int num6 = 0; num6 < A_; num6++)
				{
					if (this.m_c == Orientation.Horizontal)
					{
						array[num6].f.Height += num5 * (array[num6].f.Height / num3);
					}
					else
					{
						array[num6].f.Width += num5 * (array[num6].f.Width / num3);
					}
				}
				num3 = 0f;
				for (int num7 = 0; num7 < A_; num7++)
				{
					num3 += ((this.m_c == Orientation.Horizontal) ? array[num7].f.Height : array[num7].f.Width);
				}
				num5 = (float)num2 - num3;
				if (this.m_c == Orientation.Horizontal)
				{
					array[0].f.Height += num5;
				}
				else
				{
					array[0].f.Width += num5;
				}
			}
			int num8 = ((this.m_c == Orientation.Horizontal) ? bounds.Y : bounds.X);
			for (int num9 = 0; num9 < A_; num9++)
			{
				if (this.m_c == Orientation.Horizontal)
				{
					int num10 = Convert.ToInt32(array[num9].f.Height);
					if (num9 == A_ - 1)
					{
						num10 = bounds.Bottom - num8;
					}
					array[num9].Layout(renderer, graphics, new Rectangle(bounds.X, num8, bounds.Width, num10), floating);
					num8 += num10 + 4;
				}
				else
				{
					int num11 = Convert.ToInt32(array[num9].f.Width);
					if (num9 == A_ - 1)
					{
						num11 = bounds.Right - num8;
					}
					array[num9].Layout(renderer, graphics, new Rectangle(num8, bounds.Y, num11, bounds.Height), floating);
					num8 += num11 + 4;
				}
			}
			for (int num12 = 0; num12 < A_ - 1; num12++)
			{
				bounds = array[num12].Bounds;
				if (this.m_c == Orientation.Horizontal)
				{
					bounds.Offset(0, bounds.Height);
					bounds.Height = 4;
				}
				else
				{
					bounds.Offset(bounds.Width, 0);
					bounds.Width = 4;
				}
				this.m_d.Add(bounds);
			}
		}

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

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

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

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

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

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