using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;

using BeWo.Annotations;
using BeWo.Scheduler.ViewModel;
using BeWo.ServiceProxy;

using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;

using DevExpress.Xpf.Editors;
using DevExpress.Xpf.Scheduler;
using DevExpress.Xpf.Scheduler.UI;
using DevExpress.XtraScheduler;

namespace BeWo.Scheduler.View
{
	public partial class ResourceAppointmentEditForm : INotifyPropertyChanged
	{
		private readonly IList<CompactEmployeeDC> mEmployeeList;
		private readonly Dictionary<ValueListEntryDC, List<ResourceDC>> mCategoriesToResources;

		private List<ValueListEntryDC> _Categories;
		public List<ValueListEntryDC> Categories
		{
			get { return _Categories; }
			set { _Categories = value; OnPropertyChanged("Categories"); }
		}

		private List<ResourceDC> _ResourceList;
		public List<ResourceDC> ResourceList
		{
			get { return _ResourceList; }
			set { _ResourceList = value; OnPropertyChanged("ResourceList"); }
		}

		public ResourceAppointmentListVM ViewModel { get; set; }

		static void recurrenceControl_Loaded(object sender, RoutedEventArgs e)
		{
			LocalizeVisualChild(sender as DependencyObject);
		}

		public ResourceAppointmentFormController ResourceController { get { return Controller as ResourceAppointmentFormController; } }

		public ResourceAppointmentEditForm(ResourceAppointmentListVM vm, SchedulerControl schedulerControl,
										   Appointment appointment, IList<CompactEmployeeDC> employees,
										   Dictionary<ValueListEntryDC, List<ResourceDC>> categoriesToResources, object selectedFilterObject)
			: base(schedulerControl, appointment)
		{
			ViewModel = vm;

			mEmployeeList = employees;
			mCategoriesToResources = categoriesToResources;

			InitializeComponent();
			
			DataContext = this;
			
			Categories = mCategoriesToResources.Keys.ToList();
			ResourceList = mCategoriesToResources.First().Value;

			MonthlyRecurrenceControl.Loaded += recurrenceControl_Loaded;
			YearlyRecurrenceControl.Loaded += recurrenceControl_Loaded;

			EdtRecurrenceType.Visibility = ShouldShowRecurrence ? Visibility.Visible : Visibility.Collapsed;

			EdtRecurrenceType.CustomDisplayText += edtRecurrenceType_CustomDisplayText;

			
			ResourceCategoryComboBoxEdit.ItemsSource = Categories;

			if (selectedFilterObject != null)
			{
				// Kann Ressource(ResourceDC) oder Mitarbeiter(CompactEmployeeDC) sein (Stand: 24.10.2013)
				var typ = selectedFilterObject.GetType();
				if (typ == typeof (ResourceDC))
				{
					var selectedResource = (ResourceDC) selectedFilterObject;

					ResourceController.BeWoResourceOid = selectedResource.ResourceOid;
					ResourceComboBoxEdit.ItemsSource = mCategoriesToResources.First(x => x.Key.Equals(selectedResource.ResourceCategory)).Value;
					ResourceComboBoxEdit.EditValue = selectedResource;

					ResourceCategoryComboBoxEdit.EditValue = selectedResource.ResourceCategory;
				}
				else if (typ == typeof (CompactEmployeeDC))
				{
					ResourceController.Employee = ((CompactEmployeeDC) selectedFilterObject);
					foreach (var resource in mCategoriesToResources.Values)
					{
						var rs = resource.FirstOrDefault(abc => abc.ResourceOid.HasValue && abc.ResourceOid.Equals(appointment.CustomFields["BeWoResourceOid"]));

						if (rs == null) continue;

						ResourceComboBoxEdit.ItemsSource = mCategoriesToResources.First(kvp => kvp.Key.ValueListEntryOid.Equals(rs.ResourceCategory.ValueListEntryOid.Value)).Value;
						ResourceComboBoxEdit.EditValue = rs;

						ResourceCategoryComboBoxEdit.EditValue = rs.ResourceCategory;

						break;
					}
				}
			}
			else
			{
				foreach (var resource in mCategoriesToResources.Values)
				{
					var rs = resource.FirstOrDefault(abc => abc.ResourceOid.HasValue && abc.ResourceOid.Equals(appointment.CustomFields["BeWoResourceOid"]));

					if (rs == null) continue;

					ResourceComboBoxEdit.ItemsSource = mCategoriesToResources.First(kvp => kvp.Key.ValueListEntryOid.Equals(rs.ResourceCategory.ValueListEntryOid.Value)).Value;
					ResourceComboBoxEdit.EditValue = rs;

					ResourceCategoryComboBoxEdit.EditValue = rs.ResourceCategory;

					break;
				}
			}

			if (ResourceCategoryComboBoxEdit.SelectedIndex == -1)
			{
				ResourceCategoryComboBoxEdit.SelectedIndex = 0;
				Controller.AllDay = false;
			}

			InitEmployeeCombo();
		}

		static void edtRecurrenceType_CustomDisplayText(object sender, CustomDisplayTextEventArgs e)
		{
			var conv = new Converter.Recurrence2GermanConverter();

			e.DisplayText = (string)conv.Convert(e.EditValue, typeof(string), null, null);
			e.Handled = true;
		}

		private void InitEmployeeCombo()
		{
			var employee = ResourceController.Employee;

			if (employee == null && BeWoApp.LoggedOnEmployee.EmployeeOid.HasValue)
				ServiceFacade.DoEmployeeServiceSync(s => employee = s.LoadCompactEmployee(BeWoApp.LoggedOnEmployee.EmployeeOid.Value));

			if (mEmployeeList != null)
				foreach (var item in mEmployeeList.Where(item => employee != null && item.EmployeeOid == employee.EmployeeOid))
					employee = item;

			if (employee != null)
				PopupeditEmployee.Text = employee.ToString();

			if (ResourceController.Employee == null)
				ResourceController.Employee = employee;
		}

		private void button_ok_Click(object sender, RoutedEventArgs e)
		{
			ViewModel.NewVM.Employee = ResourceController.Employee;
			var emp = ResourceController.Employee;
			var res = ResourceController.BeWoResourceOid;

			ViewModel.NewVM.AllDay = !Appointment.AllDay;

			if (Appointment.RecurrenceInfo != null)
				ViewModel.ApplyChangesToChangedOccurencyCustomFields(emp, res, Appointment.RecurrenceIndex.ToString(), Appointment.RecurrenceInfo.Id);

			ApplyChanges();
		}

		private void button_delete_Click(object sender, RoutedEventArgs e)
		{
			DeleteAppointment();
		}

		private void button_cancel_Click(object sender, RoutedEventArgs e)
		{
			Cancel();
		}

		private void ResourceComboBoxEdit_OnEditValueChanged(object sender, EditValueChangedEventArgs e)
		{
			var ev = ((ComboBoxEdit)sender).EditValue as ResourceDC;

			var oldOid = Controller.EditedAppointmentCopy.CustomFields["BeWoResourceOid"] != null
				? (long)Controller.EditedAppointmentCopy.CustomFields["BeWoResourceOid"]
				: 0L;

			if (ev == null || !ev.ResourceOid.HasValue || oldOid.Equals(ev.ResourceOid.Value))
				return;

			ResourceController.BeWoResourceOid = ev.ResourceOid.Value;
		}

		private void ResourceCategoryComboBoxEdit_OnEditValueChanged(object sender, EditValueChangedEventArgs e)
		{
			var selectedCategory = (ValueListEntryDC)ResourceCategoryComboBoxEdit.SelectedItem;

			ResourceList = mCategoriesToResources[selectedCategory];
			ResourceComboBoxEdit.ItemsSource = ResourceList;

			var chosenOne = ResourceList.FirstOrDefault(f => selectedCategory.ValueListEntryOid.Equals(f.ResourceCategory.ValueListEntryOid) && f.ResourceOid.Equals(Appointment.CustomFields["BeWoResourceOid"] ?? Controller.EditedAppointmentCopy.CustomFields["BeWoResourceOid"]));

			if (chosenOne != null)
				ResourceComboBoxEdit.SelectedItem = chosenOne;
			else
			{
				ResourceComboBoxEdit.SelectedIndex = -1;
				ResourceComboBoxEdit.SelectedIndex = 0;
			}
		}

		public event PropertyChangedEventHandler PropertyChanged;
		[NotifyPropertyChangedInvocator]
		protected virtual void OnPropertyChanged(string propertyName)
		{
			var handler = PropertyChanged;
			if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
		}

		private void popupedit_employee_PopUpClick(object sender, RoutedEventArgs e)
		{
			PopupEmployee.IsOpen = true;
		}

		private void EmployeeSearchView_EmployeeSelected(object sender, EventArgs<CompactEmployeeDC> e)
		{
			PopupEmployee.IsOpen = false;
			PopupeditEmployee.Focus();

			var emp = e.Data;

			if (emp != null)
			{
				ResourceController.Employee = emp;
				PopupeditEmployee.Text = emp.ToString();
			}
			else
			{
				PopupeditEmployee.Text = string.Empty;
			}
		}

		public override AppointmentFormController CreateFormController(SchedulerControl schedulerControl, Appointment appointment)
		{
			return new ResourceAppointmentFormController(schedulerControl, appointment);
		}
	}

	public class ResourceAppointmentFormController : AppointmentFormController
	{
		long? SourceBeWoResourceOid
		{
			get { return (long?)SourceAppointment.CustomFields["BeWoResourceOid"]; }
			set { SourceAppointment.CustomFields["BeWoResourceOid"] = value; }
		}
		public long? BeWoResourceOid
		{
			get { return (long?)EditedAppointmentCopy.CustomFields["BeWoResourceOid"]; }
			set { EditedAppointmentCopy.CustomFields["BeWoResourceOid"] = value; }
		}

		public CompactEmployeeDC Employee
		{
			get
			{
				return (CompactEmployeeDC)EditedAppointmentCopy.CustomFields["Employee"];
			}
			set
			{
				EditedAppointmentCopy.CustomFields["Employee"] = value;
			}
		}
		private CompactEmployeeDC SourceEmployee
		{
			get
			{
				return (CompactEmployeeDC)SourceAppointment.CustomFields["Employee"];
			}
			set
			{
				SourceAppointment.CustomFields["Employee"] = value;
			}
		}

		public override bool IsAppointmentChanged()
		{
			if (base.IsAppointmentChanged())
				return true;


			if (SourceEmployee!=null && Employee !=null)
				return false;

			return SourceEmployee == null || Employee == null || !Equals(SourceEmployee, Employee);
		}

		public ResourceAppointmentFormController(SchedulerControl control, Appointment apt)
			: base(control, apt)
		{
		}

		protected override void ApplyCustomFieldsValues()
		{
			SourceEmployee = Employee;
			SourceBeWoResourceOid = BeWoResourceOid;
		}
	}
}
