/*
© 2017 Altavant Technologies Inc.
Web: http://www.altavant.com
*/

namespace Altavant.Fusion.UI.Aero
{
	using Fusion.Graphics;
	using Fusion.UI.Blocks;

	public class SplitLayer : Layer
	{
		internal class SplitOperator : ISplitOperator
		{
			private SplitLayer _source;

			public SplitOperator(SplitLayer source)
			{
				_source = source;
			}

			public OperatorType Type
			{
				get
				{
					return OperatorType.Split;
				}
			}

			public Layer Master
			{
				get
				{
					return _source.Master;
				}
				set
				{
					_source.Master = value;
				}
			}

			public Layer Detail
			{
				get
				{
					return _source.Detail;
				}
				set
				{
					_source.Detail = value;
				}
			}

			public Alignment MasterAlignment
			{
				get
				{
					return _source.MasterAlignment;
				}
				set
				{
					_source.MasterAlignment = value;
				}
			}

			public Alignment DetailAlignment
			{
				get
				{
					return _source.DetailAlignment;
				}
				set
				{
					_source.DetailAlignment = value;
				}
			}

			public Position DividerPosition
			{
				get
				{
					return _source.DividerPosition;
				}
				set
				{
					_source.DividerPosition = value;
				}
			}

			public void Layout()
			{
				_source.Layout();
			}
		}

		private Layer _master;
		private Layer _detail;
		private Alignment _masterAlignment;
		private Alignment _detailAlignment;
		private Position _dividerPosition;

		public SplitLayer()
			: this(null, null, Position.Default)
		{
			
		}

		public SplitLayer(Layer master, Layer detail, Position dividerPosition)
		{
			_master = master;
			_detail = detail;
			_masterAlignment = Alignment.Default;
			_detailAlignment = Alignment.Default;

			if (dividerPosition == null)
				_dividerPosition = Position.Default;				
			else
				_dividerPosition = dividerPosition;
		}

		public Layer Master
		{
			get
			{
				return _master;
			}
			set
			{
				if (_master != value)
				{
					if (_master != null)
					{
						if (_constructed)
							_master.FastDestroy();

						_master.Parent = null;
					}

					_master = value;

					if (_master != null)
					{
						_master.Parent = this;

						if (_constructed)
							_master.FastConstruct((ISite)_block);
					}
				}
			}
		}

		public Layer Detail
		{
			get
			{
				return _detail;
			}
			set
			{
				if (_detail != value)
				{
					if (_detail != null)
					{
						if (_constructed)
							_detail.FastDestroy();

						_detail.Parent = null;
					}

					_detail = value;

					if (_detail != null)
					{
						_detail.Parent = this;

						if (_constructed)
							_detail.FastConstruct((ISite)_block);
					}
				}
			}
		}

		public Alignment MasterAlignment
		{
			get
			{
				if (_masterAlignment == Alignment.Default)
					_masterAlignment = new Alignment();

				return _masterAlignment;
			}
			set
			{
				if (value != null)
					_masterAlignment = value;
				else
					_masterAlignment = Alignment.Default;
			}
		}

		public Alignment DetailAlignment
		{
			get
			{
				if (_detailAlignment == Alignment.Default)
					_detailAlignment = new Alignment();

				return _detailAlignment;
			}
			set
			{
				if (value != null)
					_detailAlignment = value;
				else
					_detailAlignment = Alignment.Default;
			}
		}

		public Position DividerPosition
		{
			get
			{
				if (_dividerPosition == Position.Default)
					_dividerPosition = new Position();

				return _dividerPosition;
			}
			set
			{
				if (value != null)
					_dividerPosition = value;
				else
					_dividerPosition = Position.Default;
			}
		}

		protected override void ConstructImpl(ISite site)
		{
			IPanel panel = site.AddPanel();

			if (_master != null)
				_master.FastConstruct(panel);

			if (_detail != null)
				_detail.FastConstruct(panel);

			_block = panel;
		}

		protected override void DestroyImpl()
		{
			if (_master != null)
				_master.FastDestroy();

			if (_detail != null)
				_detail.FastDestroy();
		}

		protected override BackButtonState GetBackButtonStateImpl()
		{
			if ((_master != null) && _master.Visible && (_master.GetBackButtonState() == BackButtonState.Blocked))
				return BackButtonState.Blocked;

			if ((_detail != null) && _detail.Visible && (_detail.GetBackButtonState() == BackButtonState.Blocked))
				return BackButtonState.Blocked;

			return base.GetBackButtonStateImpl();
		}

		protected override void LayoutImpl(float x, float y, float width, float height)
		{
			base.LayoutImpl(x, y, width, height);

			float sh = GetPosition(_block.Height);

			if (_master != null)
				Layout(_master, _masterAlignment, 0F, 0F, _block.Width, sh);

			if (_detail != null)
				Layout(_detail, _detailAlignment, 0F, sh, _block.Width, _block.Height - sh);
		}

		public override Area HitArea(Point pt)
		{
			Area area = null;

			if ((_master != null) && _master.Visible)
				area = _master.HitArea(pt);			

			if (area != null)
				return area;

			if ((_detail != null) && _detail.Visible)
				area = _detail.HitArea(pt);			

			if (area != null)
				return area;

			return base.HitArea(pt);
		}

		public void BecomeOperator()
		{
			_operator = new SplitOperator(this);
		}

		private float GetPosition(float value)
		{
			switch (_dividerPosition.Type)
			{
				case PositionType.Default:
					return value * 0.5F;

				case PositionType.Direct:
					return ((DirectPosition)_dividerPosition).Value;

				case PositionType.Relative:
					value = value * ((RelativePosition)_dividerPosition).Value / 100F;

					Constraint constraint = ((RelativePosition)_dividerPosition).Constraint;

					if (constraint != null)
						value = constraint.Apply(value);

					return value;
			}

			return value;
		}
	}
}