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

namespace Altavant.Fusion.UI.Lite.Controls.Toolbar
{
	using System;
	using Fusion.Graphics;

	public class Toolbar : PlaneControl
	{
		private Paddings _paddings;
		private float _itemSpacing;
		private ItemCollection _items;

		public Toolbar()
		{
			_paddings = Paddings.Default;
			_items = new ItemCollection();
		}

		public Paddings Paddings
		{
			get
			{
				if (_paddings == Paddings.Default)
					_paddings = new Paddings();

				return _paddings;
			}
			set
			{
				if (value != null)
					_paddings = value;
				else
					_paddings = Paddings.Default;
			}
		}

		public float ItemSpacing
		{
			get
			{
				return _itemSpacing; 
			}
			set
			{
				_itemSpacing = value;
			}
		}

		public IItemCollection Items
		{
			get
			{
				return _items;
			}
		}

		public void AddItem(Item item)
		{
			if (item == null)
				throw new ArgumentNullException(nameof(item));

			_items.Add(item);

			item.Toolbar = this;

			if (_constructed)
				item.Construct(_plane);
		}

		public void RemoveItem(Item item)
		{
			if (item == null)
				throw new ArgumentNullException(nameof(item));

			if (_constructed)
				item.Destroy();

			item.Toolbar = null;

			_items.Remove(item);
		}

		public void RemoveAllItems()
		{
			foreach (Item item in _items)
			{
				if (_constructed)
					item.Destroy();

				item.Toolbar = null;
			}

			_items.Clear();
		}

		public Item FindItem(string id)
		{
			foreach (Item item in _items)
			{
				if (item.Id == id)
					return item;
			}

			return null;
		}

		protected override void ConstructImpl()
		{
			foreach (Item item in _items)
			{
				item.Construct(_plane);
			}
		}

		protected override void DestroyImpl()
		{
			foreach (Item item in _items)
			{
				item.Destroy();
			}
		}

		public void Layout()
		{
			float x = _paddings.Start;
			float y = _paddings.Top;
			float width = _plane.Size.Width - _paddings.TotalHorizontal;
			float height = _plane.Size.Height - _paddings.TotalVertical;

			float mw = 0F;

			foreach (Item item in _items)
			{
				if (item.Visible && (item.Alignment.Horizontal == HorizontalAlignment.Center))
				{
					if (item.Width < 0F)
					{
						if (item.Width == Item.Fit)
							mw += item.GetPreferredSize().Width + item.Spacings.TotalHorizontal;
					}
					else
					{
						mw += item.Width + item.Spacings.TotalHorizontal;
					}

					mw += _itemSpacing;
				}
			}

			if (mw > 0F)
				mw -= _itemSpacing;

			float l = x;
			float m = x + (width - mw) / 2F;
			float r = x + width;

			foreach (Item item in _items)
			{
				if (item.Visible)
				{
					float itemX = x;
					float itemY = y;
					float itemWidth = item.Width;
					float itemHeight = item.Height;

					Size sz = Size.Default;

					if ((itemWidth == Item.Fit) || (itemHeight == Item.Fit))
						sz = item.GetPreferredSize();

					bool matchWidth = false;

					if (itemWidth < 0F)
					{
						if (itemWidth == Item.Fit)
						{
							itemWidth = sz.Width;
						}
						else
						{
							itemWidth = width - item.Spacings.TotalHorizontal;
							itemX += item.Spacings.Start;

							matchWidth = true;
						}
					}

					if (itemHeight < 0F)
					{
						if (itemHeight == Item.Fit)
							itemHeight = sz.Height;
						else
							itemHeight = height - item.Spacings.TotalVertical;
					}

					itemY = y + GetOffsetY(item, itemHeight, height);

					if (!matchWidth)
					{
						switch (item.Alignment.Horizontal)
						{
							case HorizontalAlignment.Start:
								l += item.Spacings.Start;
								itemX = l;
								l += itemWidth + item.Spacings.End + _itemSpacing;

								break;

							case HorizontalAlignment.Center:
								m += item.Spacings.Start;
								itemX = m;
								m += itemWidth + item.Spacings.End + _itemSpacing;

								break;

							case HorizontalAlignment.End:
								r -= itemWidth + item.Spacings.End;
								itemX = r;
								r -= item.Spacings.Start + _itemSpacing;

								break;
						}
					}

					item.Layout(itemX, itemY, itemWidth, itemHeight);
				}
			}
		}

		private float GetOffsetY(Item item, float itemHeight, float height)
		{
			switch (item.Alignment.Vertical)
			{
				case VerticalAlignment.Top:
					return item.Spacings.Top;

				case VerticalAlignment.Middle:
					return (height - itemHeight) / 2F;

				case VerticalAlignment.Bottom:
					return height - itemHeight - item.Spacings.Bottom;
			}

			return 0F;
		}
	}
}