using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

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

using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;

namespace BeWo.Scheduler.View
{
	public partial class RequestAnswerView : INotifyPropertyChanged
	{
		public static readonly RoutedEvent ParticipationChangedEvent = EventManager.RegisterRoutedEvent("ParticipationChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RequestAnswerView));
		public event RoutedEventHandler ParticipationChanged
		{
			add { AddHandler(ParticipationChangedEvent, value); }
			remove { RemoveHandler(ParticipationChangedEvent, value); }
		}
		void RaiseParticipationChangedEventEvent()
		{
			var newEventArgs = new RoutedEventArgs(ParticipationChangedEvent);
			RaiseEvent(newEventArgs);
		}

		public event PropertyChangedEventHandler PropertyChanged;

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

		public ObservableCollection<IBeWoAppointment> OffeneTermine { get; set; }

		private IBeWoAppointment selektierterTermin;
		public IBeWoAppointment SelektierterTermin
		{
			get { return selektierterTermin; }
			set
			{
				selektierterTermin = value;
				OnPropertyChanged("SelektierterTermin");
			}
		}

		public RequestAnswerView(IEnumerable<IBeWoAppointment> appointments, IEnumerable<IBeWoAppointment> statusUpdates)
		{
			var x = new List<IBeWoAppointment>();
			foreach (SchedulerAppointmentVM item in statusUpdates)
			{
				var emplist = (List<Employee2SchedulerAppointmentDC>) item.CustomFields["EmployeeList"];
                x.AddRange(emplist.Where(emp => emp.IsPChanged && emp.ParticipationAnswer != ParticipationAnswer.Offen && !emp.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)).Select(emp => new SchedulerAppointmentVM(new SchedulerAppointmentDC
				{
					SchedulerAppointmentOid        = item.CommitToDataContract().SchedulerAppointmentOid,
					NewSchedulerAppointmentVersion = item.CommitToDataContract().NewSchedulerAppointmentVersion,
					IsPrivate                      = item.IsPrivate,
					RecurrenceInfo                 = item.RecurrenceInfo,
					Type                           = item.EventType,
					CustomerList                   = (List<CompactCustomerDC>) item.CustomFields["CustomerList"],
					ResourceList                   = (List<ResourceDC>) item.CustomFields["ResourceList"],
					AllDay                         = item.AllDay,
					EmployeeList                   = emplist,
					Description                    = item.Description,
					EndDate                        = item.End,
					StartDate                      = item.Start,
					Location                       = item.Location,
					Subject                        = item.Subject,
					Status                         = 1,
					Originator                     = (CompactEmployeeDC) item.CustomFields["Originator"]
                }) {CustomFields = item.CustomFields, LabelId = Convert.ToInt32(emp.Employee2SchedulerAppointmentOid)}));
			}

			OffeneTermine = appointments.ToObservableCollection();
			OffeneTermine.AddRange(new List<IBeWoAppointment>(x));
			DataContext = this;
			InitializeComponent();
		}

		private void CloseButton_Click(object sender, RoutedEventArgs e)
		{
			Close();
		}

		private void Selector_OnSelected(object sender, RoutedEventArgs e)
		{
			var lv = (ListView) sender;
			SelektierterTermin = (IBeWoAppointment) lv.SelectedItem;
		}

		private void Zusagen_OnClick(object sender, RoutedEventArgs e)
		{
			var meinTermin = SelektierterTermin as SchedulerAppointmentVM;
			UpdateTeilnahme(ParticipationAnswer.Zusage, meinTermin);
		}

		private void Absagen_OnClick(object sender, RoutedEventArgs e)
		{
			var meinTermin = SelektierterTermin as SchedulerAppointmentVM;
			UpdateTeilnahme(ParticipationAnswer.Absage, meinTermin);
		}

		private void MitVorbehalt_OnClick(object sender, RoutedEventArgs e)
		{
			var meinTermin = SelektierterTermin as SchedulerAppointmentVM;
			UpdateTeilnahme(ParticipationAnswer.Vorbehalt, meinTermin);
		}

		private void UpdateTeilnahme(ParticipationAnswer antwort, SchedulerAppointmentVM termin)
		{
			termin.EmployeeList.DoForEach(e =>
			{
                if (e.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid))
                {
                    e.ParticipationAnswer = antwort;
                }
			});

			ServiceFacade.DoResourceServiceAsync(s => s.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> { termin.CommitToDataContract() }), UpdateView);
		}

		private void UpdateView(List<SchedulerAppointmentDC> aktualisierteTermine)
		{
			var zuEntfernen = new List<SchedulerAppointmentVM>();
			foreach (var dc in aktualisierteTermine)
			{
				foreach (var ivm in OffeneTermine)
				{
					var vm = ivm as SchedulerAppointmentVM;
					if (vm == null || !vm.DataContract.Equals(dc)) continue;

					var found = vm;
					found.DataContract = dc;

					UpdateViewModel(dc, ((SchedulerAppointmentVM) ivm));

					vm.UpdateCustomFields();

                    if (found.EmployeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) && a.ParticipationAnswer != ParticipationAnswer.Offen && a.IsPChanged) || found.Originator.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) && found.EmployeeList.Any(a => a.IsPC_CheckedTs != null))
						zuEntfernen.Add(found);
				}
			}
			
			this.Dispatch(() =>
			{
			    OffeneTermine = OffeneTermine.Except(zuEntfernen).ToObservableCollection();
				OnPropertyChanged("OffeneTermine");

				RaiseParticipationChangedEventEvent();
				if (OffeneTermine.Count == 0 && OTListView.Items.Count == 0)
				{
				    Close();
				}
				else
				{
				    OTListView.SelectedIndex = 0;
				}
			});
		}

		private void OK_OnClick(object sender, RoutedEventArgs e)
		{
			SelektierterTermin = OTListView.SelectedItem as IBeWoAppointment;
			if (SelektierterTermin == null || SelektierterTermin.LabelId <= 0) return;

			((List<Employee2SchedulerAppointmentDC>) SelektierterTermin.CustomFields["EmployeeList"]).Find(f => f.Employee2SchedulerAppointmentOid == SelektierterTermin.LabelId).IsPC_CheckedTs = DateTime.Now;
			((List<Employee2SchedulerAppointmentDC>) SelektierterTermin.CustomFields["EmployeeList"]).Find(f => f.Employee2SchedulerAppointmentOid == SelektierterTermin.LabelId).IsPChanged = false;

			ServiceFacade.DoResourceServiceAsync(s => s.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> {((SchedulerAppointmentVM) SelektierterTermin).DataContract}), UpdateView);
		}

		private static void UpdateViewModel(SchedulerAppointmentDC dc, SchedulerAppointmentVM vm)
		{
			vm.EmployeeList = dc.EmployeeList;
		}
	}

	public class LVItemConverter : IValueConverter
	{
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			var app = (IBeWoAppointment) value;

			if (app.LabelId <= 0)
			{
			    return string.Format("{0}: {1}", app.Start.ToShortDateString(), app.Subject);
			}

			var s = string.Empty;
			var l = ((List<Employee2SchedulerAppointmentDC>) app.CustomFields["EmployeeList"]).Find(f => f.Employee2SchedulerAppointmentOid == app.LabelId);
			switch (l.ParticipationAnswer)
			{
				case ParticipationAnswer.Zusage:
					s = "zugesagt";
					break;
				case ParticipationAnswer.Vorbehalt:
					s = "mit Vorbehalt zugesagt";
					break;
				case ParticipationAnswer.Absage:
					s = "abgesagt";
					break;
			}

			return string.Format("{0}: {1} {2} hat {3}", app.Start.ToShortDateString(), l.Employee.FirstName, l.Employee.LastName, s);
		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
	}

	public class OriginatorExtraxtor : IValueConverter
	{
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			if (value == null)
			{
			    return null;
			}

			var app = (IBeWoAppointment)value;
			var originator = (CompactEmployeeDC) app.CustomFields["Originator"];

			return originator.FirstName + " " + originator.LastName;
		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
	}

	public class Int2VisibilityConverter : IValueConverter
	{
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			if (parameter != null && parameter.Equals("ZusagenStack"))
			{
			    return System.Convert.ToInt32(value) > 0 ? Visibility.Collapsed : Visibility.Visible;
			}

			return System.Convert.ToInt32(value) > 0 ? Visibility.Visible : Visibility.Collapsed;
		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
	}
}
