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
{
	[ToolboxBitmap(typeof(DocumentContainer))]
	[Designer(typeof(DocumentContainerDesigner))]
	[DefaultEvent("ActiveDocumentChanged")]
	[ToolboxItem(true)]
	public class DocumentContainer : DockContainer, IMessageFilter
	{
		private new const int m_a = 256;

		private new const int m_b = 257;

		private new const int m_c = 9;

		private new const int m_d = 17;

		private const int e = 16;

		private DockControl f = null;

		private TD.SandDock.Rendering.BorderStyle g = TD.SandDock.Rendering.BorderStyle.Flat;

		private ArrayList h = null;

		private int i = -1;

		private bool j = true;

		private ActiveDocumentEventHandler k;

		private DocumentClosingEventHandler l;

		[Browsable(false)]
		public DockControl[] Documents
		{
			get
			{
				DockControl[] array = new DockControl[checked((uint)h.Count)];
				h.CopyTo(array);
				return array;
			}
		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[Browsable(false)]
		[DefaultValue(typeof(DockControl), null)]
		public DockControl ActiveDocument
		{
			get
			{
				return f;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException();
				}
				if (!h.Contains(value))
				{
					throw new InvalidOperationException("Specified DockControl does not belong to this DocumentContainer.");
				}
				value.Activate();
			}
		}

		internal DockControl TopMostDocument
		{
			get
			{
				if (h.Count >= 1)
				{
					return (DockControl)h[h.Count - 1];
				}
				return null;
			}
		}

		[DefaultValue(true)]
		[Category("Behavior")]
		[Description("Indicates whether the ctrl-tab and ctrl-shift-tab sequences will navigate between documents.")]
		public bool KeyboardNavigation
		{
			get
			{
				return j;
			}
			set
			{
				j = value;
			}
		}

		[DefaultValue(typeof(TD.SandDock.Rendering.BorderStyle), "Flat")]
		[Category("Appearance")]
		[Description("The type of border to be drawn around the control.")]
		public TD.SandDock.Rendering.BorderStyle BorderStyle
		{
			get
			{
				return g;
			}
			set
			{
				g = value;
				OnResize(EventArgs.Empty);
			}
		}

		public override Rectangle DisplayRectangle
		{
			get
			{
				Rectangle displayRectangle = base.DisplayRectangle;
				switch (g)
				{
				case TD.SandDock.Rendering.BorderStyle.Flat:
				case TD.SandDock.Rendering.BorderStyle.RaisedThin:
				case TD.SandDock.Rendering.BorderStyle.SunkenThin:
					displayRectangle.Inflate(-1, -1);
					break;
				case TD.SandDock.Rendering.BorderStyle.RaisedThick:
				case TD.SandDock.Rendering.BorderStyle.SunkenThick:
					displayRectangle.Inflate(-2, -2);
					break;
				}
				return displayRectangle;
			}
		}

		protected override Size DefaultSize => new Size(300, 300);

		[Browsable(true)]
		[DefaultValue(typeof(DockStyle), "Fill")]
		public override DockStyle Dock
		{
			get
			{
				return base.Dock;
			}
			set
			{
				base.Dock = value;
			}
		}

		[Browsable(true)]
		public override RendererBase Renderer
		{
			get
			{
				return base.Renderer;
			}
			set
			{
				base.Renderer = value;
			}
		}

		public event ActiveDocumentEventHandler ActiveDocumentChanged
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				k = (ActiveDocumentEventHandler)Delegate.Combine(k, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				k = (ActiveDocumentEventHandler)Delegate.Remove(k, value);
			}
		}

		public event DocumentClosingEventHandler DocumentClosing
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				l = (DocumentClosingEventHandler)Delegate.Combine(l, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				l = (DocumentClosingEventHandler)Delegate.Remove(l, value);
			}
		}

		public DocumentContainer()
		{
			h = new ArrayList();
			Dock = DockStyle.Fill;
		}

		public void AddDocument(DockControl control)
		{
			if (h.Contains(control))
			{
				throw new ArgumentException("Document already belongs to this Document Container.");
			}
			ControlLayoutSystem controlLayoutSystem = b(LayoutSystem);
			if (controlLayoutSystem == null)
			{
				controlLayoutSystem = new DocumentLayoutSystem();
				LayoutSystem.LayoutSystems.Add(controlLayoutSystem);
			}
			controlLayoutSystem.Controls.Add(control);
		}

		public void RemoveDocument(DockControl control)
		{
			if (!h.Contains(control))
			{
				throw new ArgumentException("Document not found.");
			}
			TD.SandDock.g.a(control);
		}

		internal new void c(DockControl A_0)
		{
			if (A_0 == f)
			{
				return;
			}
			if (i == -1)
			{
				if (h.Contains(A_0))
				{
					h.Remove(A_0);
				}
				h.Add(A_0);
			}
			DockControl a_ = f;
			f = A_0;
			ActiveDocumentEventArgs activeDocumentEventArgs = new ActiveDocumentEventArgs(a_, f);
			OnActiveDocumentChanged(activeDocumentEventArgs);
			a(a_);
		}

		private void a(DockControl A_0)
		{
			if (A_0 != null && A_0.b != null && f != A_0 && base.c.Contains(A_0.b))
			{
				a(A_0.b, A_0.b.Bounds);
				Invalidate(A_0.b.Bounds);
			}
			if (f != null && f.b != null && base.c.Contains(f.b))
			{
				a(f.b, f.b.Bounds);
				Invalidate(f.b.Bounds);
			}
		}

		internal override void LayoutSystemsChanged()
		{
			base.LayoutSystemsChanged();
			b();
			if (f != null && (f.b == null || !base.c.Contains(f.b)))
			{
				DockControl a_ = f;
				f = ((h.Count != 0) ? ((DockControl)h[h.Count - 1]) : null);
				ActiveDocumentEventArgs activeDocumentEventArgs = new ActiveDocumentEventArgs(a_, f);
				OnActiveDocumentChanged(activeDocumentEventArgs);
				a(a_);
			}
		}

		protected virtual void OnActiveDocumentChanged(ActiveDocumentEventArgs e)
		{
			if (k != null)
			{
				k(this, e);
			}
		}

		private void b()
		{
			ArrayList arrayList = new ArrayList(20);
			foreach (LayoutSystemBase item in base.c)
			{
				if (!(item is ControlLayoutSystem))
				{
					continue;
				}
				foreach (DockControl control in ((ControlLayoutSystem)item).Controls)
				{
					arrayList.Add(control);
				}
			}
			for (int num = h.Count - 1; num >= 0; num--)
			{
				if (!arrayList.Contains(h[num]))
				{
					h.RemoveAt(num);
				}
			}
			foreach (DockControl item2 in arrayList)
			{
				if (!h.Contains(item2))
				{
					h.Add(item2);
				}
			}
		}

		internal void d(DockControl A_0)
		{
			if (!h.Contains(A_0))
			{
				h.Add(A_0);
			}
		}

		internal void b(DockControl A_0)
		{
			if (h.Contains(A_0))
			{
				h.Remove(A_0);
			}
			if (f == A_0)
			{
				DockControl a_ = f;
				f = ((h.Count != 0) ? ((DockControl)h[h.Count - 1]) : null);
				ActiveDocumentEventArgs activeDocumentEventArgs = new ActiveDocumentEventArgs(a_, f);
				OnActiveDocumentChanged(activeDocumentEventArgs);
				a(a_);
			}
		}

		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
		{
			if ((keyData == (Keys.Tab | Keys.Control) || keyData == (Keys.Tab | Keys.Shift | Keys.Control)) && j)
			{
				if (h.Count == 1)
				{
					return true;
				}
				if ((keyData & Keys.Shift) == Keys.Shift)
				{
					i = h.Count - 1;
				}
				else
				{
					i = 1;
				}
				a();
				Application.AddMessageFilter(this);
				return true;
			}
			return base.ProcessCmdKey(ref msg, keyData);
		}

		private void a()
		{
			if (i > h.Count)
			{
				i = h.Count;
			}
			int index = h.Count - 1 - i;
			DockControl dockControl = (DockControl)h[index];
			dockControl.b.SelectedControl = dockControl;
			dockControl.Activate();
		}

		bool IMessageFilter.PreFilterMessage(ref Message m)
		{
			if (m.Msg == 256 && m.WParam.ToInt32() == 9)
			{
				if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
				{
					i--;
				}
				else
				{
					i++;
				}
				if (i > h.Count - 1)
				{
					i = 0;
				}
				if (i < 0)
				{
					i = h.Count - 1;
				}
				a();
				return true;
			}
			if (m.Msg == 256 && m.WParam.ToInt32() == 16)
			{
				return true;
			}
			if ((m.Msg == 257 && m.WParam.ToInt32() == 17) || m.Msg == 256)
			{
				if (f != null)
				{
					h.Remove(f);
					h.Add(f);
				}
				i = -1;
				Application.RemoveMessageFilter(this);
				return true;
			}
			return false;
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			base.OnPaint(e);
			DockControl.a(this, e.Graphics, g);
		}

		protected internal virtual void OnDocumentClosing(DocumentClosingEventArgs e)
		{
			if (l != null)
			{
				l(this, e);
			}
		}

		protected override void OnPaintBackground(PaintEventArgs pevent)
		{
			base.WorkingRenderer.DrawDocumentContainerBackground(pevent.Graphics, DisplayRectangle);
		}
	}
}
