using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OPlanner {

	public delegate void BasicEventHandler();
	public delegate void SenderEventHandler(object sender);
	public delegate void UpdateEventHandler(object sender, UpdateType updateType, List<OBaseObject> objects, bool updatePropertiesPanel);
	public delegate void SenderStringEventHandler(object sender, string info);

	public enum ToolType {
		None, Select, Rotate, MeasureDistance, CreateControl, CreateStart, CreateFinish, CreateCrossingPoint, CreateTransparentArea, CreateCourseDescriptions, CreateLine, CreateTapedRoute, CreateText, CreateInvisiblePoint, CreateDrinksPoint, CreateOOBCross, CreateOOBArea, CreateAreaBlock, CreateFirstAidPoint, CreateUncrossableBoundary, RemovePoint, CreateNormalPoint, CreateQuadraticBezierPoint
	}

	public enum CreateMode {
		None, Normal, Course
	}

	public enum DrawingMode {
		None, Freehand, Line
	}

	public enum CourseViewType {
		Outline, Preview, HideAll
	}

	public enum UpdateType {
		Move, Code, Drawing, FreehandDrawing, Rotate, Redraw, Display, Description
	}

	public class OCurrentInfoBase {

		protected OPlannerData data;
		public OPlannerData Data {
			get { return data; }
		}

		public OCurrentInfoBase() {
			SelectedObjects = new List<OBaseObject>();
			CopiedObjects = new List<CopyPasteObject>();
			Clear();
		}

		private void LoadClonedData(OPlannerData newData) {
			data = newData;
			if (data == null) {
				Clear();
			} else {
				List<OBaseObject> tempSelected = new List<OBaseObject>(SelectedObjects);
				Course tempCourse = SelectedCourse;
				SelectedCourse = null;
				SelectedObjects.Clear();
				if (tempCourse != null) {
					for (int i = 0; i < data.Courses.Count; i++) {
						if (data.Courses[i].Name == tempCourse.Name) {
							SelectedCourse = data.Courses[i];
						}
					}
				}
				for (int i = 0; i < tempSelected.Count; i++) {
					Course course = (Course)tempSelected[i].Parent.GetObject(typeof(Course));
					if (course != null) {
						Course newCourse = data.GetCourseByName(course.Name);
						if (newCourse == null) {
							continue;
						}
						OBaseObject obj = newCourse.GetObjectByCode(tempSelected[i].ObjectCode);
						if (obj != null) {
							SelectedObjects.Add(obj);
						}
					} else {
						OBaseObject obj = data.GetObjectByCode(tempSelected[i].ObjectCode);
						if (obj != null) {
							SelectedObjects.Add(obj);
						}
					}
				}
			}
		}

		protected void Clear() {
			data = null;
			SelectedCourse = null;
			CourseViewType = CourseViewType.Outline;
			SelectedTool = ToolType.Select;
			CreateMode = CreateMode.None;
			DrawingMode = DrawingMode.None;
			SelectedObjects.Clear();
			CopiedObjects.Clear();
			zoomLevel = 1;
		}

		public OCurrentInfoBase Clone() {
			OCurrentInfoBase clone = new OCurrentInfoBase();
			clone.CourseViewType = CourseViewType;
			clone.SelectedTool = SelectedTool;
			clone.SelectedObjects = new List<OBaseObject>(SelectedObjects);
			clone.SelectedCourse = SelectedCourse;
			clone.ZoomLevel = ZoomLevel;
			clone.LoadClonedData(data.Clone());
			return clone;
		}

		public DescriptionManager DescriptionManager;
		public Course SelectedCourse;
		public CourseViewType CourseViewType;
		public ToolType SelectedTool;
		public CreateMode CreateMode;
		public DrawingMode DrawingMode;
		public List<OBaseObject> SelectedObjects;
		public List<CopyPasteObject> CopiedObjects;
		double zoomLevel;
		public double ZoomLevel {
			get {
				return zoomLevel;
			}
			set {
				zoomLevel = value;
			}
		}

	}

	public class OCurrentInfo : OCurrentInfoBase {

		public void LoadInfo(OCurrentInfoBase baseInfo) {
			//DescriptionManager = baseInfo.DescriptionManager;
			SelectedCourse = baseInfo.SelectedCourse;
			SelectedObjects = baseInfo.SelectedObjects;
			CourseViewType = baseInfo.CourseViewType;
			data = baseInfo.Data;
			OnDataLoaded();
		}

		public void LoadData(OPlannerData newData) {
			Clear();
			data = newData;
			OnDataLoaded();
		}

		public event BasicEventHandler DataLoaded;
		public event SenderStringEventHandler DataChanged;
		public event SenderStringEventHandler DataChanging;
		public event SenderEventHandler ToolSelected;
		public event SenderEventHandler CourseCreated;
		public event SenderEventHandler CourseDeleted;
		public event SenderEventHandler CourseSelected;
		public event SenderEventHandler ObjectsCreated;
		public event SenderEventHandler ObjectsDeleted;
		public event SenderEventHandler ObjectsSelected;
		public event SenderEventHandler ObjectsDeselected;
		public event UpdateEventHandler ObjectsUpdated;
		public event SenderEventHandler CourseViewModeChanged;
		public event SenderEventHandler MapUpdated;

		private void OnDataLoaded() {
			if (DataLoaded != null) {
				DataLoaded.Invoke();
			}
		}
		public void InvokeDataChanged(object sender, string info) {
			if (DataChanged != null) {
				DataChanged.Invoke(sender, info);
			}
		}
		public void InvokeDataChanging(object sender, string info) {
			if (DataChanging != null) {
				DataChanging.Invoke(sender, info);
			}
		}
		public void InvokeToolSelected(object sender) {
			if (ToolSelected != null) {
				ToolSelected.Invoke(sender);
			}
		}
		public void InvokeCourseCreated(object sender) {
			if (CourseCreated != null) {
				CourseCreated.Invoke(sender);
			}
		}
		public void InvokeCourseDeleted(object sender) {
			if (CourseDeleted != null) {
				CourseDeleted.Invoke(sender);
			}
		}
		public void InvokeCourseSelected(object sender) {
			if (CourseSelected != null) {
				CourseSelected.Invoke(sender);
			}
		}
		public void InvokeObjectsCreated(object sender) {
			if (ObjectsCreated != null) {
				ObjectsCreated.Invoke(sender);
			}
		}
		public void InvokeObjectsDeleted(object sender) {
			if (ObjectsDeleted != null) {
				ObjectsDeleted.Invoke(sender);
			}
		}
		public void InvokeObjectsSelected(object sender) {
			if (ObjectsSelected != null) {
				ObjectsSelected.Invoke(sender);
			}
		}
		public void InvokeObjectsDeselected(object sender) {
			if (ObjectsDeselected != null) {
				ObjectsDeselected.Invoke(sender);
			}
		}
		public void InvokeObjectsUpdated(object sender, UpdateType updateType, List<OBaseObject> objects, bool updatePropertiesPanel) {
			if (ObjectsUpdated != null) {
				ObjectsUpdated.Invoke(sender, updateType, objects, updatePropertiesPanel);
			}
		}
		public void InvokeCourseViewModeChanged(object sender) {
			if (CourseViewModeChanged != null) {
				CourseViewModeChanged.Invoke(sender);
			}
		}
		public void InvokeMapUpdated(object sender) {
			if (MapUpdated != null) {
				MapUpdated.Invoke(sender);
			}
		}

	}

}
