using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

using BeWo.Controls.Controls.Calendar;
using BeWo.Core;
using BeWo.ServiceProxy;
using BeWo.ViewModel;
using BeWo.ViewModel.ListViewModel;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using DevExpress.Xpf.Editors;


namespace BeWo.View.Detail
{
    public partial class BookingView
    {
        private readonly Dictionary<ValueListEntryDC, List<ResourceDC>> _CategoriesToResources;

        private ValueListEntryDC _Category;

        private ResourceDC _Resource;

        private BookingVM _ViewModel;

        public ObservableCollection<CompactEmployeeDC> EmployeeCollection { get; set; }

        public BookingView(Dictionary<ValueListEntryDC, List<ResourceDC>> pCategoriesToResources, List<CompactEmployeeDC> pPossibleEmployees, CompactEmployeeDC pSelectedEmployee)
        {
            this.InitializeComponent();
            EmployeeCollection = pPossibleEmployees.ToObservableCollection();
            DataContext = this;

            this._CategoriesToResources = pCategoriesToResources;

            combobox_newEmployee.ItemsSource = EmployeeCollection;
            
            this.combobox_newEmployee.SelectedItem = pSelectedEmployee;
            this.combobox_editEmployee.ItemsSource = EmployeeCollection;
            this.combobox_resourceCategories.ItemsSource = this._CategoriesToResources.Keys;
            this.combobox_resourceCategories.SelectedItem = this._CategoriesToResources.ElementAt(0).Key;
            this.listbox_resources.ItemsSource = this._CategoriesToResources.ElementAt(0).Value;
            this.combobox_newVMResource.ItemsSource = this._CategoriesToResources.ElementAt(0).Value;
            
            this._Category = this._CategoriesToResources.ElementAt(0).Key;

            this.combobox_resourceCategories.SelectionChanged += this.combobox_resourceCategories_SelectionChanged;
            this.listbox_resources.SelectionChanged += this.listbox_resource_SelectionChanged;

            this.calendar.CalendarStartDateChanged += (s, e) => this.OnCalenderDateChanged();
            this.calendar.DaysToShowCountChanged += (s, e) => this.OnCalenderDateChanged();

            DependencyPropertyDescriptor.FromProperty(DateEdit.EditValueProperty, typeof(DateEdit)).AddValueChanged(
                this.EDIT_datepickerStartDate, 
                (s, e) =>
                    {
                        if (this.ViewModel.EditVM != null)
                        {
                            this.ViewModel.EditVM.UpdatePossibleFrequencies(this.EDIT_datepickerStartDate.DateTime);
                        }
                    });
            
            this.ReloadViewModel();
            
            if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Create) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.CreateAll) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Edit) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.EditAll) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Delete) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.DeleteAll))
            {
                this.groupBoxBookingNewEdit.IsEnabled = false;
                this.expander_edit_booking.IsEnabled = false;
                this.expander_new_booking.IsEnabled = false;
                this.groupBoxBookingNewEdit.Visibility = Visibility.Collapsed;
            }
            else
            {
                if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Create) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.CreateAll))
                {
                    this.expander_new_booking.IsEnabled = false;
                    this.expander_new_booking.Visibility = Visibility.Collapsed;
                }

                if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Edit) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.EditAll) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Delete) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.DeleteAll))
                {
                    this.expander_edit_booking.IsEnabled = false;
                    this.expander_edit_booking.Visibility = Visibility.Collapsed;
                }
                else
                {
                    if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Edit) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.EditAll))
                    {
                        this.button_editBooking.IsEnabled = false;
                        this.button_editBooking.Visibility = Visibility.Collapsed;
                    }

                    if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_Delete) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.DeleteAll))
                    {
                        this.button_deleteBooking.IsEnabled = false;
                        this.button_deleteBooking.Visibility = Visibility.Collapsed;
                    }
                }
            }

            
        }

        public static Dictionary<string, int> Hours
        {
            get
            {
                var lResult = new Dictionary<string, int>();
                for (int i = 0; i < 24; i++)
                {
                    lResult.Add(string.Format("{0:00}", i), i);
                }

                return lResult;
            }
        }

        public static Dictionary<string, int> Minutes
        {
            get
            {
                var lResult = new Dictionary<string, int>();
                for (int i = 0; i < 60; i += 15)
                {
                    lResult.Add(string.Format("{0:00}", i), i);
                }

                return lResult;
            }
        }

        public override bool CanDelete
        {
            get
            {
                return !this.expander_new_booking.IsExpanded && this.expander_edit_booking.IsExpanded;
            }
        }

        public override bool IsDirty
        {
            get
            {
                return this.ViewModel != null ? this.ViewModel.IsDirty : false;
            }
        }

        public override string Title
        {
            get
            {
                return "Ressourcenbuchung";
            }
        }

        internal BookingVM ViewModel
        {
            get
            {
                return this._ViewModel;
            }

            set
            {
                this._ViewModel = value;
                this.grid_root.DataContext = value;
                if (this.calendar.IsLoaded)
                {
                    this.Refresh();
                }
            }
        }

        public override void Delete()
        {
            this.DeleteBooking();
        }

        protected override void Save()
        {
            var lToDos = new List<Action<IResourceService>>();

            if (this.ViewModel.AddedCount > 0)
            {
                lToDos.Add(s => s.InsertNewBookings(this.ViewModel.CommitAdded()));
            }

            if (this.ViewModel.ChangedCount > 0)
            {
                lToDos.Add(s => s.UpdateBookings(this.ViewModel.CommitChanged()));
            }

            if (this.ViewModel.RemovedCount > 0)
            {
                lToDos.Add(s => s.DeleteBookings(this.ViewModel.GetRemoved().ToDictionary(dc => dc.SequenceOid.Value, dc => dc.SequenceVersion.Value)));
            }

            ServiceFacade.DoMultipleResourceServicesAsync(lToDos, this.ReloadViewModel);

            this.expander_edit_booking.IsExpanded = false;
            this.expander_new_booking.IsExpanded = true;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.listbox_resources.SelectedIndex = -1;
        }

        private void CommitEdit()
        {
            this.ViewModel.EditAppointment.Duration = this.GetEditDuration();
            this.ViewModel.EditAppointment.Notice = this.EDIT_textboxNotice.Text;
            if (this.ViewModel.EditVM != null)
            {
                this.ViewModel.EditVM.Frequency = (ResourceBookingFrequencyType)this.EDIT_comboFrequency.SelectedValue;
                this.ViewModel.EditVM.RepeatInterval = (int)this.EDIT_spineditIntervall.Value;
                this.ViewModel.EditVM.SequenceEnd = this.EDIT_datepickerSequenceEnd.DateTime;
            }
        }

        private void DeleteBooking()
        {
            if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_AllowEditResourcesFromOtherEmployees))
            {
                if (this.ViewModel.EditVM != null)
                {
                    if (this.ViewModel.EditVM.Employee != null && !BeWoApp.LoggedOnUser.Employee.Equals(this.ViewModel.EditVM.Employee))
                    {
                        MessageBox.Show("Sie besitzen nicht die erforderlichen Rechte um eine Buchung eines anderen Mitarbeiters zu löschen!", "BeWoPlaner", MessageBoxButton.OK);
                        return;
                    }
                }
                else
                {
                    var lSequence = this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment);
                    if (lSequence != null && lSequence.Employee != null)
                    {
                        if (!BeWoApp.LoggedOnUser.Employee.Equals(lSequence.Employee))
                        {
                            MessageBox.Show("Sie besitzen nicht die erforderlichen Rechte um eine Buchung eines anderen Mitarbeiters zu löschen!", "BeWoPlaner", MessageBoxButton.OK);
                            return;
                        }
                    }
                }
            }

            if (this.ViewModel.EditVM == null)
            {
                bool r = this.calendar.Appointments.Remove(this.ViewModel.EditAppointment);
                var lSequence = this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment);
                lSequence.DeleteElement(lSequence.GetSequencePosition(this.ViewModel.EditAppointment));
                this.ViewModel.EditAppointment = null;
            }
            else
            {
                if (this.ViewModel.EditVM.Frequency == ResourceBookingFrequencyType.Once || MessageBox.Show("Wenn sie das erste Element einer Serie löschen, wird die gesamte Serie gelöscht.", "Löschen", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    this.calendar.Appointments.RemoveRange(this.ViewModel.EditVM.AppointmentsInSpan);
                    this.ViewModel.DeleteEditVM();
                    this.ViewModel.EditAppointment = null;
                }
            }

            this.expander_edit_booking.IsExpanded = false;
            this.expander_new_booking.IsExpanded = true;
        }

        private void DoPossibleCheckAsync(bool pForNewVM, Action<bool> pCallBack)
        {
            List<Appointment> lProblems = null;
            DateTimeSpan lSpanToCheckOnServer = null;

            if (pForNewVM)
            {
                lProblems = BookingVM.GetOverlappingWholeSequence(this.ViewModel.NewVM, this.ViewModel.VMList.Where(vm => vm.Resource.ResourceOid == this.ViewModel.NewVM.Resource.ResourceOid).ToList());
                lSpanToCheckOnServer = new DateTimeSpan { StartDateTime = this.ViewModel.NewVM.RootAppointment.Duration.StartDateTime, EndDateTime = this.ViewModel.NewVM.SequenceEnd };
            }
            else if (this.ViewModel.EditVM != null)
            {
                lProblems = BookingVM.GetOverlappingWholeSequence(this.ViewModel.EditVM, this.ViewModel.VMList.Where(vm => vm.Resource.ResourceOid == this.ViewModel.EditVM.Resource.ResourceOid).ToList());
                lSpanToCheckOnServer = new DateTimeSpan { StartDateTime = this.ViewModel.EditVM.RootAppointment.Duration.StartDateTime, EndDateTime = this.ViewModel.EditVM.SequenceEnd };
            }
            else
            {
                lProblems = BookingVM.GetOverlappingSingleBooking(this.ViewModel.EditAppointment, this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment), this.ViewModel.VMList.Where(vm => vm.Resource.ResourceOid == this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment).Resource.ResourceOid).ToList());
                lSpanToCheckOnServer = this.ViewModel.EditAppointment.Duration.Clone();
            }

            long lResourceOid = pForNewVM ? this.ViewModel.NewVM.Resource.ResourceOid.Value : this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment).Resource.ResourceOid.Value;

            ServiceFacade.DoResourceServiceAsync(
                s => s.GetAllBookingsByResource(lResourceOid, lSpanToCheckOnServer.StartDateTime, lSpanToCheckOnServer.EndDateTime), 
                lServerBookings => this.Dispatch(
                    delegate
                        {
                            lServerBookings.RemoveRange(dc1 => this.ViewModel.DCBackup.SingleOrDefault(dc2 => dc1.SequenceOid == dc2.SequenceOid) != null);

                            if (lServerBookings.Count > 0)
                            {
                                var lVMs = lServerBookings.Select(dc => new BookingSequenceVM(dc)).ToList();
                                if (pForNewVM)
                                {
                                    lProblems.AddRange(BookingVM.GetOverlappingWholeSequence(this.ViewModel.NewVM, lVMs));
                                }
                                else if (this.ViewModel.EditVM != null)
                                {
                                    lProblems.AddRange(BookingVM.GetOverlappingWholeSequence(this.ViewModel.EditVM, lVMs));
                                }
                                else
                                {
                                    lProblems.AddRange(BookingVM.GetOverlappingSingleBooking(this.ViewModel.EditAppointment, this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment), this.ViewModel.VMList));
                                }
                            }

                            if (lProblems.Count == 0)
                            {
                                pCallBack(true);
                                return;
                            }

                            StringBuilder lSb = new StringBuilder("Die Buchung kann leider nicht ");
                            lSb.Append(pForNewVM ? "angelegt " : "geändert ");
                            lSb.Append("werden, da folgende Termine bereits belegt sind:\n\n");
                            lProblems.DoForEach(iProblem => lSb.Append(iProblem.Duration.ToString() + "\n"));

                            MessageBox.Show(lSb.ToString(), "Nicht möglich", MessageBoxButton.OK, MessageBoxImage.Warning);
                            pCallBack(false);
                        }));
        }

        private void EditAppointment(Appointment pAppointment)
        {
            if (this.ViewModel.EditAppointment != pAppointment)
            {
                var lSequence = this.ViewModel.GetAppointmentsSequence(pAppointment);

                if (lSequence.GetSequencePosition(pAppointment) == 0)
                {
                    this.ViewModel.EditVM = lSequence;
                }
                else
                {
                    this.ViewModel.EditVM = null;
                }

                this.ViewModel.EditAppointment = pAppointment;

                this.InitEdit();
            }
        }

        private DateTimeSpan GetEditDuration()
        {
            return new DateTimeSpan { StartDateTime = this.EDIT_datepickerStartDate.DateTime.Date.AddHours((int)this.EDIT_comboStartHours.SelectedValue).AddMinutes((int)this.EDIT_comboStartMinutes.SelectedValue), EndDateTime = this.EDIT_datepickerEndDate.DateTime.Date.AddHours((int)this.EDIT_comboEndHours.SelectedValue).AddMinutes((int)this.EDIT_comboEndMinutes.SelectedValue) };
        }

        private void InitEdit()
        {
            this.expander_edit_booking.IsExpanded = true;
            this.expander_new_booking.IsExpanded = false;

            this.EDIT_datepickerStartDate.DateTime = this.ViewModel.EditAppointment.Duration.StartDate;
            this.EDIT_comboStartHours.SelectedValue = this.ViewModel.EditAppointment.Duration.StartHours;
            this.EDIT_comboStartMinutes.SelectedValue = this.ViewModel.EditAppointment.Duration.StartMinutes;
            this.EDIT_datepickerEndDate.DateTime = this.ViewModel.EditAppointment.Duration.EndDate;
            this.EDIT_comboEndHours.SelectedValue = this.ViewModel.EditAppointment.Duration.EndHours;
            this.EDIT_comboEndMinutes.SelectedValue = this.ViewModel.EditAppointment.Duration.EndMinutes;
            this.EDIT_textboxNotice.Text = this.ViewModel.EditAppointment.Notice;
            if (this.ViewModel.EditVM != null)
            {
                this.EDIT_comboFrequency.SelectedValue = this.ViewModel.EditVM.Frequency;
                this.EDIT_spineditIntervall.Value = this.ViewModel.EditVM.RepeatInterval;
                this.EDIT_datepickerSequenceEnd.DateTime = this.ViewModel.EditVM.SequenceEnd;
            }
        }

        private void OnCalenderDateChanged()
        {
            int? lPos = null;
            BookingSequenceVM lSeq = null;
            if (this.ViewModel.EditAppointment != null)
            {
                lSeq = this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment);
                lPos = lSeq.GetSequencePosition(this.ViewModel.EditAppointment);
            }

            DateTime lEnd = this.calendar.CalendarStartDate.AddDays(this.calendar.DaysToShowCount);

            var lStart = this.calendar.CalendarStartDate;
            try
            {
                ServiceFacade.DoResourceServiceAsync(
                    s => s.GetAllBookings(lStart, lEnd), 
                    r => this.Dispatch(
                        delegate
                            {
                                this.ViewModel.DCBackup.AddRange(r.Where(newdc => this.ViewModel.DCBackup.SingleOrDefault(dc => dc.SequenceOid == newdc.SequenceOid) == null));

                                this.Refresh();

                                if (lPos != null)
                                {
                                    var lApp = lSeq.GetAppointment(lPos.Value);
                                    if (lApp != null)
                                    {
                                        this.calendar.Select(lApp);
                                    }
                                    else
                                    {
                                        this.ViewModel.EditAppointment = null;
                                        this.ViewModel.EditVM = null;
                                        this.expander_edit_booking.IsExpanded = false;
                                        this.expander_new_booking.IsExpanded = true;
                                    }
                                }
                            }));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

	    internal void Refresh()
	    {
		    if (calendar.IsLoaded && ViewModel != null)
		    {
			    calendar.Appointments.Clear();
			    calendar.Appointments.AddRange(_Resource != null
				    ? ViewModel.GetAppointmentsByResource(_Resource.ResourceOid.Value, calendar.DaySpan)
				    : ViewModel.GetAppointmentsByCategory(_Category.ValueListEntryOid.Value, calendar.DaySpan));
		    }
	    }

        private void ReloadViewModel()
        {
            this.Dispatch(
                delegate
                    {
                        VMFactory.CreateBookingVMAsync(
                            this.calendar.DaySpan, 
                            r => this.Dispatch(
                                delegate
                                    {
                                        this.ViewModel = r;
                                        this.Refresh();
                                    }));
                    });
        }

        
        private void button_createBooking_Click(object sender, RoutedEventArgs e)
        {
            var lRootStart = this.ViewModel.NewVM.RootAppointment.Duration.StartDateTime;
            var lRoot = this.ViewModel.NewVM.RootAppointment;

            if (this.ViewModel.NewVM.Frequency != ResourceBookingFrequencyType.Once && this.ViewModel.NewVM.SequenceEnd < lRoot.Duration.EndDateTime)
            {
                MessageBox.Show("Das Enddatum der Serie muss größer oder gleich dem Enddatum des ersten Serienelements sein!", "Fehler", MessageBoxButton.OK);
                return;
            }

            var lStartDateTime = this.NEW_datepickerStartDate.DateTime.AddHours((int)this.NEW_comboboxStartHour.SelectedValue).AddMinutes((int)this.NEW_comboboxStartMinute.SelectedValue);
            var lEndDateTime = this.NEW_datepickerEndDate.DateTime.AddHours((int)this.NEW_comboboxEndHour.SelectedValue).AddMinutes((int)this.NEW_comboboxEndMinute.SelectedValue);

            if (lStartDateTime >= lEndDateTime)
            {
                MessageBox.Show("Das Startdatum muss vor dem Enddatum liegen!", "Fehler", MessageBoxButton.OK);
                return;
            }

            if (lEndDateTime < DateTime.Now)
            {
                if (MessageBox.Show("Das Enddatum liegt in der Vergangenheit. Wollen Sie wirklich speichern?", "Speichern", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
                {
                    return;
                }
            }

            if (this._Resource == null)
            {
                if (this.combobox_newVMResource.SelectedItem == null)
                {
                    MessageBox.Show("Bitte wählen sie aus, welche Ressource Sie buchen möchten!", "Fehler", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                this.ViewModel.NewVM.Resource = this.combobox_newVMResource.SelectedItem as ResourceDC;
            }
            else
            {
                this.ViewModel.NewVM.Resource = this._Resource;
            }

            this.ViewModel.NewVM.RootAppointment.Tag = this.combobox_newEmployee.SelectedItem;

            if (this.ViewModel.NewVM.Frequency == ResourceBookingFrequencyType.Once)
            {
                this.ViewModel.NewVM.SequenceEnd = lRoot.Duration.EndDateTime;
            }

            this.DoPossibleCheckAsync(
                true, 
                r => this.Dispatch(
                    delegate
                        {
                            if (!r)
                            {
                                return;
                            }

                            if (!lRootStart.InBetween(this.calendar.CalendarStartDate, this.calendar.CalendarStartDate.AddDays(this.calendar.DaysToShowCount), false))
                            {
                                this.ViewModel.AddNewVMToList();
                                this.calendar.CalendarStartDate = lRootStart.Date;
                            }
                            else
                            {
                                this.ViewModel.NewVM.SpanToConsider = this.calendar.DaySpan;
                                this.calendar.Appointments.AddRange(this.ViewModel.NewVM.AppointmentsInSpan);
                                this.ViewModel.AddNewVMToList();
                            }

                            this.calendar.Select(lRoot);
                        }));
        }

        private void button_deleteBooking_Click(object sender, RoutedEventArgs e)
        {
            this.DeleteBooking();
        }

        private void button_editBooking_Click(object sender, RoutedEventArgs e)
        {
            if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ResourceBookingView_AllowEditResourcesFromOtherEmployees))
            {
                if (this.ViewModel.EditVM != null)
                {
                    if (this.ViewModel.EditVM.Employee != null && !BeWoApp.LoggedOnUser.Employee.Equals(this.ViewModel.EditVM.Employee))
                    {
                        MessageBox.Show("Sie besitzen nicht die erforderlichen Rechte um eine Buchung eines anderen Mitarbeiters zu ändern!", "BeWoPlaner", MessageBoxButton.OK);
                        return;
                    }
                }
                else
                {
                    var lSequence = this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment);
                    if (lSequence != null && lSequence.Employee != null)
                    {
                        if (!BeWoApp.LoggedOnUser.Employee.Equals(lSequence.Employee))
                        {
                            MessageBox.Show("Sie besitzen nicht die erforderlichen Rechte um eine Buchung eines anderen Mitarbeiters zu ändern!", "BeWoPlaner", MessageBoxButton.OK);
                            return;
                        }
                    }
                }
            }

            var lDuration = this.GetEditDuration();

            if (lDuration.StartDateTime >= lDuration.EndDateTime)
            {
                MessageBox.Show("Das Startdatum muss vor dem Enddatum liegen!", "Fehler", MessageBoxButton.OK);
                return;
            }

            if (this.ViewModel.EditVM != null)
            {
                this.EDIT_datepickerSequenceEnd.DateTime = this.EDIT_datepickerSequenceEnd.DateTime.Date.AddHours(23).AddMinutes(59);
                if ((ResourceBookingFrequencyType)this.EDIT_comboFrequency.SelectedValue != ResourceBookingFrequencyType.Once && this.EDIT_datepickerSequenceEnd.DateTime < this.ViewModel.EditAppointment.Duration.EndDateTime)
                {
                    MessageBox.Show("Das Enddatum der Serie muss größer oder gleich dem Enddatum des ersten Serienelements sein!", "Fehler", MessageBoxButton.OK);
                    return;
                }

                if (this.ViewModel.EditVM.Frequency == ResourceBookingFrequencyType.Once || MessageBox.Show("Das erste Element einer Serie kann nicht einzelnd geändert werden.\n\n " + "Klicken Sie OK wenn sie die Änderungen auf alle Elemente der Serie anwenden wollen.\n Änderungen die Sie an einzelnen Elementen der Serie vorgenommen haben gehen dabei verloren.", "Serie ändern", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    var lAppointmentsInSpan = this.ViewModel.EditVM.AppointmentsInSpan;

                    var lDurationBak = this.ViewModel.EditAppointment.Duration.Clone();
                    var lSeqenceEndBak = this.ViewModel.EditVM.SequenceEnd;
                    var lFrequencyBak = this.ViewModel.EditVM.Frequency;
                    var lRepeatIntervalBak = this.ViewModel.EditVM.RepeatInterval;

                    this.CommitEdit();

                    this.DoPossibleCheckAsync(
                        false, 
                        r => this.Dispatch(
                            delegate
                                {
                                    if (!r)
                                    {
                                        this.ViewModel.EditAppointment.Duration = lDurationBak;
                                        this.ViewModel.EditVM.SequenceEnd = lSeqenceEndBak;
                                        this.ViewModel.EditVM.Frequency = lFrequencyBak;
                                        this.ViewModel.EditVM.RepeatInterval = lRepeatIntervalBak;
                                        return;
                                    }

                                    this.calendar.Appointments.RemoveRange(lAppointmentsInSpan);

                                    this.ViewModel.EditVM.ClearChanged();

                                    if (this.ViewModel.EditVM.Frequency == ResourceBookingFrequencyType.Once)
                                    {
                                        this.ViewModel.EditVM.SequenceEnd = this.ViewModel.EditAppointment.Duration.EndDateTime;
                                    }

                                    if (!this.ViewModel.EditAppointment.Duration.StartDateTime.InBetween(this.calendar.DaySpan, false))
                                    {
                                        this.ViewModel.EditVM.SpanToConsider = new DateTimeSpan { StartDateTime = this.ViewModel.EditAppointment.Duration.StartDate, EndDateTime = this.ViewModel.EditAppointment.Duration.StartDate.AddDays(this.calendar.DaysToShowCount) };
                                        this.calendar.CalendarStartDate = this.ViewModel.EditAppointment.Duration.StartDate;
                                    }
                                    else
                                    {
                                        this.calendar.Appointments.AddRange(this.ViewModel.EditVM.AppointmentsInSpan);
                                    }

                                    this.calendar.Select(this.ViewModel.EditAppointment);
                                }));
                }
            }
            else
            {
                var lSequence = this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment);

                if (lDuration.StartDateTime < lSequence.RootAppointment.Duration.StartDateTime)
                {
                    MessageBox.Show("Ein Serienelement kann nicht früher starten als die Serie!", "Fehler", MessageBoxButton.OK);
                    return;
                }

                if (lDuration.EndDateTime > lSequence.SequenceEnd)
                {
                    MessageBox.Show("Ein Serienelement kann nicht später enden als die Serie!", "Fehler", MessageBoxButton.OK);
                    return;
                }

                var lBck = this.ViewModel.EditAppointment.Duration.Clone();

                this.ViewModel.EditAppointment.Duration = lDuration;

                this.DoPossibleCheckAsync(
                    false, 
                    r => this.Dispatch(
                        delegate
                            {
                                if (!r)
                                {
                                    this.ViewModel.EditAppointment.Duration = lBck;
                                    return;
                                }

                                this.CommitEdit();

                                lSequence.ChangeElement(lSequence.GetSequencePosition(this.ViewModel.EditAppointment), this.ViewModel.EditAppointment);
                                if (!this.ViewModel.EditAppointment.Duration.StartDateTime.InBetween(this.calendar.DaySpan, false))
                                {
                                    this.calendar.CalendarStartDate = this.ViewModel.EditAppointment.Duration.StartDate;
                                }

                                this.calendar.Select(this.ViewModel.EditAppointment);
                            }));
            }
        }

        private void button_showRootElement_Click(object sender, RoutedEventArgs e)
        {
            var lSequence = this.ViewModel.GetAppointmentsSequence(this.ViewModel.EditAppointment);
            var lRootAppointment = lSequence.RootAppointment;

            if (!this.calendar.Appointments.Contains(lRootAppointment))
            {
                this.calendar.CalendarStartDate = lRootAppointment.Duration.StartDate;
            }

            this.calendar.Select(lRootAppointment);
        }

        private void calendar_AppointmentDeselected(object sender, EventArgs<Appointment> e)
        {
            this.expander_edit_booking.IsExpanded = false;
            this.expander_new_booking.IsExpanded = true;
        }

        private void calendar_AppointmentSelected(object sender, EventArgs<Appointment> e)
        {
            this.EditAppointment(e.Data);
        }

        private void combobox_resourceCategories_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this._Resource = null;
            this._Category = (ValueListEntryDC)this.combobox_resourceCategories.SelectedItem;
            this.listbox_resources.ItemsSource = this._CategoriesToResources[(ValueListEntryDC)this.combobox_resourceCategories.SelectedItem];
            this.combobox_newVMResource.ItemsSource = this._CategoriesToResources[(ValueListEntryDC)this.combobox_resourceCategories.SelectedItem];
            this.combobox_newVMResource.SelectedItem = null;
            this.Refresh();
        }

        private void expander_edit_booking_Loaded(object sender, RoutedEventArgs e)
        {
            var lEditToggle = this.expander_edit_booking.FindFirstVisualChild<ToggleButton>();
            if (lEditToggle != null)
            {
                lEditToggle.PreviewMouseDown += this.lEditToggle_PreviewMouseDown;
            }
        }

        private void expander_new_booking_Expanded(object sender, RoutedEventArgs e)
        {
            if (this.IsLoaded)
            {
                this.expander_edit_booking.IsExpanded = false;
                this.calendar.Deselect(this.ViewModel.EditAppointment);
                this.ViewModel.EditAppointment = null;
                this.ViewModel.EditVM = null;
            }
        }

        private void lEditToggle_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!this.expander_edit_booking.IsExpanded && this.ViewModel.EditAppointment == null)
            {
                MessageBox.Show("Um eine Buchung zu bearbeiten, klicken Sie bitte im Belegungsplan auf den entsprechenden Balken", "Buchung bearbeiten", MessageBoxButton.OK, MessageBoxImage.Information);
                e.Handled = true;
            }
        }

        private void listbox_resource_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
	        _Resource = listbox_resources.SelectedItem as ResourceDC;
	        if (_Resource != null)
	        {
		        combobox_newVMResource.SelectedItem = _Resource;
	        }

	        Refresh();

	        expander_edit_booking.IsExpanded = false;
	        expander_new_booking.IsExpanded = true;
        }

        private void Combobox_newEmployee_OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var combobox = (ComboBox) sender;
            var selectedI = combobox.SelectedItem as CompactEmployeeDC;

            if (selectedI == null || !BeWoApp.LoggedOnUser.HasRight(UserRightType.EmployeeView_View))
                return;

            VMFactory.CreateEmployeeVMAsync(selectedI.EmployeeOid,
                cb => this.Dispatch(() => BeWoUtils.OpenModalViewWindow<EmployeeVM, EmployeeDC, BookingView>(cb, this, 
                    () => this.Dispatch(() => BeWoUtils.UpdateAllViews(selectedI)))));
        }
    }
}