using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace OpenSEMI.Ctrlib.Controls
{
	public class Slot : ContentControl
	{
		public static readonly DependencyProperty ViewTypeProperty;

		public static readonly DependencyProperty WaferStatusProperty;

		public static readonly DependencyProperty SlotIDProperty;

		public static readonly DependencyProperty ModuleIDProperty;

		public static readonly DependencyProperty IsDragSourceProperty;

		public static readonly DependencyProperty IsDropTargetProperty;

		public static readonly DependencyProperty IsDragEnterProperty;

		public static readonly DependencyProperty IsSelectedProperty;

		public static readonly DependencyProperty HasWaferProperty;

		public static readonly DependencyProperty BorderStatusProperty;

		public static readonly DependencyProperty SourceNameProperty;

		public static readonly DependencyProperty CanDragDropProperty;

		public static readonly DependencyProperty WaferTooltipProperty;

		public static readonly DependencyProperty WaferTooltipExtProperty;

		public static readonly DependencyProperty SeasoningWaferTypeProperty;

		public static readonly DependencyProperty DuplicatedVisibilityProperty;

        public static readonly DependencyProperty SlotWidthProperty;

        public bool IsDraggable
		{
			get;
			set;
		}

		public bool IsLeftMouseDown
		{
			get;
			set;
		}

		public string ViewType
		{
			get
			{
				return (string)GetValue(ViewTypeProperty);
			}
			set
			{
				SetValue(ViewTypeProperty, value);
			}
		}

		public int WaferStatus
		{
			get
			{
				return (int)GetValue(WaferStatusProperty);
			}
			set
			{
				SetValue(WaferStatusProperty, value);
			}
		}

		public int SlotID
		{
			get
			{
				return (int)GetValue(SlotIDProperty);
			}
			set
			{
				SetValue(SlotIDProperty, value);
			}
		}

		public string ModuleID
		{
			get
			{
				return (string)GetValue(ModuleIDProperty);
			}
			set
			{
				SetValue(ModuleIDProperty, value);
			}
		}

		public bool IsDragSource
		{
			get
			{
				return (bool)GetValue(IsDragSourceProperty);
			}
			set
			{
				SetValue(IsDragSourceProperty, value);
			}
		}

		public bool IsDropTarget
		{
			get
			{
				return (bool)GetValue(IsDropTargetProperty);
			}
			set
			{
				SetValue(IsDropTargetProperty, value);
			}
		}

		public bool IsDragEnter
		{
			get
			{
				return (bool)GetValue(IsDragEnterProperty);
			}
			set
			{
				SetValue(IsDragEnterProperty, value);
			}
		}

		public bool IsSelected
		{
			get
			{
				return (bool)GetValue(IsSelectedProperty);
			}
			set
			{
				SetValue(IsSelectedProperty, value);
			}
		}

		public bool HasWafer
		{
			get
			{
				return (bool)GetValue(HasWaferProperty);
			}
			set
			{
				SetValue(HasWaferProperty, value);
			}
		}

		public SlotBorderStatus BorderStatus
		{
			get
			{
				return (SlotBorderStatus)GetValue(BorderStatusProperty);
			}
			set
			{
				SetValue(BorderStatusProperty, value);
			}
		}

		public string SourceName
		{
			get
			{
				return (string)GetValue(SourceNameProperty);
			}
			set
			{
				SetValue(SourceNameProperty, value);
			}
		}

		public bool CanDragDrop
		{
			get
			{
				return (bool)GetValue(CanDragDropProperty);
			}
			set
			{
				SetValue(CanDragDropProperty, value);
			}
		}

		public string WaferTooltip
		{
			get
			{
				return (string)GetValue(WaferTooltipProperty);
			}
			set
			{
				SetValue(WaferTooltipProperty, value);
			}
		}

		public string WaferTooltipExt
		{
			get
			{
				return (string)GetValue(WaferTooltipExtProperty);
			}
			set
			{
				SetValue(WaferTooltipExtProperty, value);
			}
		}

		public string SeasoningWaferType
		{
			get
			{
				return (string)GetValue(SeasoningWaferTypeProperty);
			}
			set
			{
				SetValue(SeasoningWaferTypeProperty, value);
			}
		}

		public Visibility DuplicatedVisibility
		{
			get
			{
				return (Visibility)GetValue(DuplicatedVisibilityProperty);
			}
			set
			{
				SetValue(DuplicatedVisibilityProperty, value);
			}
		}
        public int SlotWidth
        {
            get
            {
                return (int)GetValue(SlotWidthProperty);
            }
            set
            {
                SetValue(SlotWidthProperty, value);
            }
        }
        public event MouseButtonEventHandler SlotMouseButtonDown;

		public event DragDropHandler WaferTransferStarted;

		static Slot()
		{
			ViewTypeProperty = DependencyProperty.Register("ViewType", typeof(string), typeof(Slot), new UIPropertyMetadata("Front"));
			WaferStatusProperty = DependencyProperty.Register("WaferStatus", typeof(int), typeof(Slot), new UIPropertyMetadata(0, WaferStatusChangedCallBack));
			SlotIDProperty = DependencyProperty.Register("SlotID", typeof(int), typeof(Slot), new UIPropertyMetadata(-1));
			ModuleIDProperty = DependencyProperty.Register("ModuleID", typeof(string), typeof(Slot), new UIPropertyMetadata(string.Empty));
			IsDragSourceProperty = DependencyProperty.Register("IsDragSource", typeof(bool), typeof(Slot), new UIPropertyMetadata(false, IsDragSourcePropertyChangedCallBack));
			IsDropTargetProperty = DependencyProperty.Register("IsDropTarget", typeof(bool), typeof(Slot), new UIPropertyMetadata(false, IsDropTargetPropertyChangedCallBack));
			IsDragEnterProperty = DependencyProperty.Register("IsDragEnter", typeof(bool), typeof(Slot), new UIPropertyMetadata(false, IsDragEnterPropertyChangedCallBack));
			IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(Slot), new UIPropertyMetadata(false, IsSelectedPropertyChangedCallBack));
			HasWaferProperty = DependencyProperty.Register("HasWafer", typeof(bool), typeof(Slot), new UIPropertyMetadata(false, HasWaferChanged));
			BorderStatusProperty = DependencyProperty.Register("BorderStatus", typeof(SlotBorderStatus), typeof(Slot), new UIPropertyMetadata(SlotBorderStatus.None));
			SourceNameProperty = DependencyProperty.Register("SourceName", typeof(string), typeof(Slot), new UIPropertyMetadata(string.Empty));
			CanDragDropProperty = DependencyProperty.Register("CanDragDrop", typeof(bool), typeof(Slot), new UIPropertyMetadata(true, CanDragDropPropertyChangedCallBack));
			WaferTooltipProperty = DependencyProperty.Register("WaferTooltip", typeof(string), typeof(Slot), new PropertyMetadata(string.Empty));
			WaferTooltipExtProperty = DependencyProperty.Register("WaferTooltipExt", typeof(string), typeof(Slot), new PropertyMetadata(string.Empty));
			SeasoningWaferTypeProperty = DependencyProperty.Register("SeasoningWaferType", typeof(string), typeof(Slot), new PropertyMetadata(string.Empty));
			DuplicatedVisibilityProperty = DependencyProperty.Register("DuplicatedVisibility", typeof(Visibility), typeof(Slot), new UIPropertyMetadata(Visibility.Collapsed));
            SlotWidthProperty = DependencyProperty.Register("SlotWidth", typeof(int), typeof(Slot), new UIPropertyMetadata(90));

            FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(Slot), new FrameworkPropertyMetadata(typeof(Slot)));
		}

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();
			DragDropStatusControl(this);
		}

		protected override void OnDragEnter(DragEventArgs e)
		{
			base.OnDragEnter(e);
			IsDragEnter = true;
		}

		protected override void OnDragLeave(DragEventArgs e)
		{
			base.OnDragLeave(e);
			IsDragEnter = false;
		}

		protected override void OnMouseDown(MouseButtonEventArgs e)
		{
			base.OnMouseDown(e);
			if (MouseButtonState.Pressed == e.LeftButton)
			{
				IsLeftMouseDown = true;
			}
			e.Handled = true;
		}

		protected override void OnMouseUp(MouseButtonEventArgs e)
		{
			base.OnMouseUp(e);
			IsLeftMouseDown = false;
			this.SlotMouseButtonDown?.Invoke(this, e);
		}

		protected override void OnMouseEnter(MouseEventArgs e)
		{
			base.OnMouseEnter(e);
			BorderStatus |= SlotBorderStatus.MouseOver;
		}

		protected override void OnMouseLeave(MouseEventArgs e)
		{
			base.OnMouseLeave(e);
			IsLeftMouseDown = false;
			BorderStatus &= ~SlotBorderStatus.MouseOver;
		}

		private static void DragDropStatusControl(Slot p_slot)
		{
			p_slot.AllowDrop = false;
			p_slot.IsDraggable = false;
			if (p_slot.CanDragDrop)
			{
				if (!p_slot.IsDropTarget && p_slot.WaferStatus == 0)
				{
					p_slot.AllowDrop = true;
				}
				if (!p_slot.IsDragSource && p_slot.WaferStatus != 0)
				{
					p_slot.IsDraggable = true;
				}
			}
		}

		private static void IsDropTargetPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs args)
		{
			Slot slot = d as Slot;
			if (slot.IsDropTarget)
			{
				slot.BorderStatus |= SlotBorderStatus.TransferTarget;
			}
			else
			{
				slot.BorderStatus &= ~SlotBorderStatus.TransferTarget;
			}
			DragDropStatusControl(slot);
		}

		private static void IsDragSourcePropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs args)
		{
			Slot slot = d as Slot;
			if (slot.IsDragSource)
			{
				slot.BorderStatus |= SlotBorderStatus.TransferSource;
			}
			else
			{
				slot.BorderStatus &= ~SlotBorderStatus.TransferSource;
			}
			DragDropStatusControl(slot);
		}

		private static void IsSelectedPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs args)
		{
			Slot slot = d as Slot;
			if (slot.IsSelected)
			{
				slot.BorderStatus |= SlotBorderStatus.Selected;
			}
			else
			{
				slot.BorderStatus &= ~SlotBorderStatus.Selected;
			}
		}

		private static void CanDragDropPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs args)
		{
			Slot p_slot = d as Slot;
			DragDropStatusControl(p_slot);
		}

		private static void IsDragEnterPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs args)
		{
			Slot slot = d as Slot;
			if (slot.IsDragEnter)
			{
				slot.BorderStatus |= SlotBorderStatus.TransferTarget;
			}
			else
			{
				slot.BorderStatus &= ~SlotBorderStatus.TransferTarget;
			}
		}

		private static void WaferStatusChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs args)
		{
			Slot slot = d as Slot;
			slot.IsDragSource = false;
			slot.IsDropTarget = false;
			slot.IsDragEnter = false;
			DragDropStatusControl(slot);
		}

		public static void HasWaferChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			Slot slot = d as Slot;
			if (slot != null)
			{
				if (slot.HasWafer)
				{
					slot.WaferStatus = 7;
				}
				else
				{
					slot.WaferStatus = 0;
				}
			}
		}

		protected override void OnPreviewMouseMove(MouseEventArgs e)
		{
			base.OnPreviewMouseMove(e);
			if (e.LeftButton == MouseButtonState.Pressed && IsDraggable && IsLeftMouseDown)
			{
				DataObject data = new DataObject(typeof(Slot), this);
				DragDrop.DoDragDrop(this, data, DragDropEffects.Move);
			}
		}

		protected override void OnDrop(DragEventArgs e)
		{
			if (base.AllowDrop)
			{
				try
				{
					IDataObject data = e.Data;
					if (data.GetDataPresent(typeof(Slot)))
					{
						Slot slot = (Slot)data.GetData(typeof(Slot));
						slot.IsDragSource = true;
						IsDropTarget = true;
						if (this.WaferTransferStarted != null)
						{
							DragDropEventArgs e2 = new DragDropEventArgs(slot, this);
							this.WaferTransferStarted(this, e2);
						}
					}
					else
					{
						string moduleID = e.Data.GetData("Station").ToString();
						int slotID = (int)e.Data.GetData("Slot");
						Slot p_TranferFrom = new Slot
						{
							ModuleID = moduleID,
							SlotID = slotID
						};
						if (this.WaferTransferStarted != null)
						{
							DragDropEventArgs e3 = new DragDropEventArgs(p_TranferFrom, this);
							this.WaferTransferStarted(this, e3);
						}
					}
				}
				catch
				{
				}
			}
		}

		public bool IsValidSlot()
		{
			if (ModuleID.Length > 0 && SlotID >= 0)
			{
				return true;
			}
			return false;
		}

		public bool IsSameSlot(Slot slot)
		{
			if (slot.IsValidSlot() && IsValidSlot() && ModuleID == slot.ModuleID && SlotID == slot.SlotID)
			{
				return true;
			}
			return false;
		}

		public void ClearDragDropStatus()
		{
			IsDragEnter = false;
			IsDragSource = false;
			IsDropTarget = false;
		}
	}
}