using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace OPlanner {

	public class OControlVisual : OObjectVisual {

		private bool isNumberDragging;
		private bool hasNumberMoved;
		private Point dragNumberStart;

		public OControlVisual() {
			isNumberDragging = false;
			hasNumberMoved = false;
		}

		private OControlTextVisual numberText;

		public override void Select() {
			base.Select();
			if (numberText != null && info.SelectedObjects.Count == 1) {
				numberText.Select();
			}
		}

		public override void Deselect() {
			base.Deselect();
			if (numberText != null) {
				numberText.Deselect();
			}
		}

		protected override void PositionObject() {
			base.PositionObject();
			OCourseControl obj = (OCourseControl)ObjectData.GetObject(typeof(OCourseControl));
			if (obj == null) {
				return;
			}
			if (numberText == null) {
				return;
			}
			Point offset = obj.GetNumberOffset();
			Point centre = GetCentre();
			Size numberSize = numberText.GetSize();
			Canvas.SetLeft(numberText, centre.X + offset.X - numberSize.Width / 2);
			Canvas.SetTop(numberText, centre.Y + offset.Y - numberSize.Height / 2);
		}

		protected override void DrawObject() {
			base.DrawObject();
			if (info.CourseViewType == CourseViewType.Outline) {
				return;
			}
			OCourseControl obj = (OCourseControl)ObjectData.GetObject(typeof(OCourseControl));
			if (obj == null) {
				return;
			}
			if (numberText == null) {
				numberText = new OControlTextVisual();
				numberText.MouseLeftButtonDown += new MouseButtonEventHandler(NumberMouseDown);
				numberText.MouseLeftButtonUp += new MouseButtonEventHandler(NumberMouseUp);
				numberText.MouseMove += new MouseEventHandler(NumberMouseMove);
				numberText.LostMouseCapture += new MouseEventHandler(NumberLostMouseCapture);
				IMapObject mapObj = (IMapObject)ObjectData.GetObject(typeof(IMapObject));
				if (mapObj != null) {
					Canvas.SetZIndex(numberText, mapObj.Depth);
				}
				parentCanvas.AddOObjectVisual(numberText);
			}
			RedrawNumberText();
		}

		private void RedrawNumberText() {
			OCourseControl obj = (OCourseControl)ObjectData.GetObject(typeof(OCourseControl));
			if (obj == null) {
				return;
			}
			string text = obj.GetNumberText();
			if (text == null || text == "") {
				ClearText();
				return;
			}
			numberText.SetFontColour(new SolidColorBrush((Color)ColorConverter.ConvertFromString(info.Data.ControlColour)));
			double fontSize = 0;
			if (obj.GetCourse() == null) {
				fontSize = info.Data.NumberSize * 0.7;
			} else {
				fontSize = info.Data.NumberSize;
			}
			numberText.SetFontSize(fontSize);
			numberText.Text = text;
			if (IsSelected) {
				numberText.Select();
			}
			IOpacityObject opacityObj = (IOpacityObject)ObjectData.GetObject(typeof(IOpacityObject));
			if (opacityObj != null) {
				if (opacityObj.Opacity != 100 || numberText.Opacity != 1) {
					numberText.Opacity = opacityObj.Opacity / 100;
				}
			}
		}

		private void ClearText() {
			if (numberText != null) {
				parentCanvas.RemoveOObjectVisual(numberText);
				numberText = null;
			}
		}

		public override void CleanUp() {
			base.CleanUp();
			ClearText();
		}

		private void NumberLostMouseCapture(object sender, MouseEventArgs e) {
			OCourseControl obj = (OCourseControl)ObjectData.GetObject(typeof(OCourseControl));
			if (obj == null) {
				return;
			}
			OControlTextVisual oObject = (OControlTextVisual)sender;
			if (isNumberDragging) {
				if (hasNumberMoved) {
					Point mousePos = Mouse.GetPosition(parentCanvas);
					if (mousePos.X < 0) {
						mousePos.X = 0;
					}
					if (mousePos.Y < 0) {
						mousePos.Y = 0;
					}
					if (mousePos.X > parentCanvas.CanvasWidth) {
						mousePos.X = parentCanvas.CanvasWidth;
					}
					if (mousePos.Y > parentCanvas.CanvasHeight) {
						mousePos.Y = parentCanvas.CanvasHeight;
					}
					Point centre = GetCentre();
					obj.NumberXOffset = mousePos.X - dragNumberStart.X - centre.X;
					obj.NumberYOffset = mousePos.Y - dragNumberStart.Y - centre.Y;
					info.InvokeDataChanged(parentCanvas, "Move Number");
					info.InvokeObjectsUpdated(parentCanvas, UpdateType.Redraw, new List<OBaseObject>(new OBaseObject[]{ObjectData}), true);
					hasNumberMoved = false;
				}
				isNumberDragging = false;
				parentCanvas.UpdateCursor();
			}
		}

		private void NumberMouseDown(object sender, MouseButtonEventArgs e) {
			OCourseControl obj = (OCourseControl)ObjectData.GetObject(typeof(OCourseControl));
			if (obj == null) {
				return;
			}
			if (obj.NumberOffsetType != AutoManual.Manual) {
				return;
			}
			OControlTextVisual oObject = (OControlTextVisual)sender;
			if (oObject.IsSelected != true) {
				return;
			}
			Point mousePos = Mouse.GetPosition(parentCanvas);
			Size size = oObject.GetSize();
			dragNumberStart = new Point(mousePos.X - Canvas.GetLeft(oObject) - size.Width / 2, mousePos.Y - Canvas.GetTop(oObject) - size.Height / 2);
			isNumberDragging = true;
			Mouse.Capture(oObject);
			parentCanvas.SetArrowCursor();
		}

		private void NumberMouseMove(object sender, MouseEventArgs e) {
			OCourseControl obj = (OCourseControl)ObjectData.GetObject(typeof(OCourseControl));
			if (obj == null) {
				return;
			}
			OControlTextVisual oObject = (OControlTextVisual)sender;
			if (isNumberDragging) {
				Point mousePos = Mouse.GetPosition(parentCanvas);
				if (mousePos.X < 0) {
					mousePos.X = 0;
				}
				if (mousePos.Y < 0) {
					mousePos.Y = 0;
				}
				if (mousePos.X > parentCanvas.CanvasWidth) {
					mousePos.X = parentCanvas.CanvasWidth;
				}
				if (mousePos.Y > parentCanvas.CanvasHeight) {
					mousePos.Y = parentCanvas.CanvasHeight;
				}
				double x = Canvas.GetLeft(oObject);
				double y = Canvas.GetTop(oObject);
				if (!hasNumberMoved) {
					if (mousePos.X - x != dragNumberStart.X || mousePos.Y - y != dragNumberStart.Y) {
						info.InvokeDataChanging(parentCanvas, "Move Number");
						hasNumberMoved = true;
					}
				}
				if (hasNumberMoved) {
					Point centre = GetCentre();
					obj.NumberXOffset = mousePos.X - dragNumberStart.X - centre.X;
					obj.NumberYOffset = mousePos.Y - dragNumberStart.Y - centre.Y;
					UpdateObject(UpdateType.Redraw);
				}
			}
		}

		private void NumberMouseUp(object sender, MouseButtonEventArgs e) {
			if (isNumberDragging) {
				Mouse.Capture(null);
			}
		}

	}

}
