using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using BeWo.Core;
using BeWo.Core.Service;
using BeWo.ServiceProxy;
using BeWo.Validation;
using BeWo.ViewModel;

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

using DevExpress.Xpf.Editors.Settings;
using DevExpress.Xpf.Grid;
using Color = System.Drawing.Color;

namespace BeWo.View.Detail
{
	public partial class EmployeeView : BeWoView
	{
		private EmployeeVM _ViewModel;

		private GridControl grid_AbsenceTimes;
		private GridControl grid_Overtimes;
		private GridControl grid_Customers;

		private bool initTabIndex;

        

		public EmployeeView(EmployeeVM pEmployeeDC)
		{
			InitializeComponent();
            combobox_brush.ItemTemplateSelector = new ComboBoxTemplateSelector(combobox_brush);
			ViewModel = pEmployeeDC;

			bool noticeVisible = false;
			bool extendedPropsVisible = false;

			if (BeWoApp.Mandator.BeWoClientType == 3)
			{
				//Köln Ring
				extendedPropsVisible = true;
			}
			else if (BeWoApp.Mandator.BeWoClientType == 4)
			{
				//Betreuwo
				if (BeWoApp.LoggedOnUser.HasRight(UserRightType.Employee_AllowEditExtendedProperties))
					noticeVisible = true;
			}

			if (!noticeVisible)
				noticeGroup.Visibility = Visibility.Collapsed;
			if (!extendedPropsVisible)
				extendedPropertyGroup.Visibility = Visibility.Collapsed;

		    if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ChatSettings))
		    {
		        tabitem_chatservice.Visibility = Visibility.Collapsed;
		    }
                

			if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.Employee_AllowEditContracts))
				tabitem_contract.Visibility = Visibility.Collapsed;

			if (BeWoApp.LoggedOnUser.HasRight(UserRightType.OvertimeView))
			{
				OvertimeTabItem.Visibility = Visibility.Visible;	
			}
			else
				OvertimeTabItem.Visibility = Visibility.Collapsed;


			// HACK: Force the devexpress grid to end editing when the mouse is over savebutton
			// by setting the focus to another element. 
			MouseMove += (s, e) =>
			{
				if ((grid_AbsenceTimes == null || !grid_AbsenceTimes.IsVisible) &&
					(grid_Customers == null || !grid_Customers.IsVisible) && (grid_Overtimes == null || !grid_Overtimes.IsVisible))
				{
					return;
				}

				Point p = e.GetPosition(btnSave);

				if (p.X >= 0 && p.X < btnSave.ActualWidth && p.Y >= 0 && p.Y < btnSave.ActualHeight)
				{
					root.Focus();
				}
			};

			tabcontrol_contracts.Loaded += tabcontrol_contracts_Loaded;

			
			chkArchiviert.IsChecked = ViewModel.IsArchived;

			if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.Employee_AllowArchiving))
			{
				lblArchiviert.Visibility = Visibility.Hidden;
				chkArchiviert.Visibility = Visibility.Hidden;
			}

			tabitem_documents.Visibility = Visibility.Collapsed;
			
			if (BeWoApp.LoggedOnUser.HasRight(UserRightType.DocumentsAllowViewAll) || (BeWoApp.LoggedOnUser.HasRight(UserRightType.DokumenteMitarbeiter) && BeWoApp.LoggedOnEmployee.EmployeeOid == pEmployeeDC.DataContract.EmployeeOid))
			{
				tabitem_documents.Visibility = Visibility.Visible;
			}
		}

		public override bool IsDirty
		{
			get { return ViewModel != null && ViewModel.IsDirty; }
		}

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

		internal override DependencyObject ValidationOnSaveRootElement
		{
			get { return grid_details; }
		}

		internal EmployeeVM ViewModel
		{
			get { return _ViewModel; }

			set
			{
				_ViewModel = value;
				DataContext = value;

				if (tabcontrol_contracts.Items.Count == 0 && _ViewModel.Contracts.VMList.Count > 0)
					initTabIndex = true;
				else
					SetTabIndexToLastContract();
			}
		}

		private void tabcontrol_contracts_Loaded(object sender, RoutedEventArgs e)
		{
			if (initTabIndex)
			{
				SetTabIndexToLastContract();
				initTabIndex = false;
			}
		}

		private void SetTabIndexToLastContract()
		{
			//DateTime maxDate = DateTime.MinValue;

			if (tabcontrol_contracts.Items.Count > 0)
				tabcontrol_contracts.SelectedIndex = tabcontrol_contracts.Items.Count - 1;
		}

		protected override UserRightType[] GetSaveDemands()
		{
			if (ViewModel.IsNew)
				return new[] {UserRightType.CreateAll, UserRightType.EmployeeView_Create};
			if (ViewModel.DataContract.EmployeeOid == BeWoApp.LoggedOnEmployee.EmployeeOid)
				return new[] {UserRightType.EditAll, UserRightType.EmployeeView_Edit, UserRightType.Employee_AllowEditOwnEmployees};
			return new[] {UserRightType.EditAll, UserRightType.EmployeeView_Edit};
		}

		

		protected override void Save()
		{
			if (!ValidateContracts())
			{
				return;
			}

			EmployeeDC lDataContract = ViewModel.CommitToDataContract();
			try
			{
				if (ViewModel.IsNew)
				{
					IsDoneWithInsertOrUpdate = false;
					ServiceFacade.DoEmployeeServiceAsync(s => s.InsertNewEmployee(lDataContract), ReloadViewModel);
				}
				else
				{
					IsDoneWithInsertOrUpdate = false;
					ServiceFacade.DoEmployeeServiceAsync(s => s.UpdateEmployee(lDataContract), ReloadViewModel);
				}

				Cache.GetInstance().ClearEmployees();
				BeWoApp.MainControl.ResetView(UIContext.Employee);
			}
			catch (FaultException<BeWoFault>)
			{
				MessageBox.Show(
					"Dieser Datensatz wurde in der Zwischenzeit von einem anderen Benutzer geändert. Klicken Sie Ok um den Datansatz erneut zu laden. Ihre Änderungen gehen dabei leider verloren.");
				ReloadViewModel(lDataContract.EmployeeOid.Value);
			}
		}

		private bool ValidateContracts()
		{
			var count = ViewModel.Contracts.VMList.Count(c => !c.ContractEndDate.HasValue);
			if (count > 1)
			{
				MessageBox.Show(String.Format("Es darf nur ein unbefristeter Vetrag angelegt werden. Bitte überprüfen Sie das \"Befristet bis\" Datum der angelegten Verträge."), "Ungültiger Vetrag", MessageBoxButton.OK);
				return false;
			}
			foreach (var contract in ViewModel.Contracts.VMList)
			{
				if (contract.EntryDate.HasValue && contract.ContractEndDate.HasValue &&
				    contract.EntryDate.Value > contract.ContractEndDate.Value)
				{
					MessageBox.Show(String.Format("Das Startdatum eines Vertrags ist größer als das Enddatum. Bitte überprüfen Sie die angelegten Verträge."), "Ungültiger Vetrag", MessageBoxButton.OK);
					return false;	
				}
			}

			return true;

		}

		private void CustomerSearchView_CustomerSelected(object sender, EventArgs<CompactCustomerDC> e)
		{
			popup_customer.IsOpen = false;
			ViewModel.CustomerRelations.NewVM.Customer = e.Data;
			popupedit_customerRelations.Focus();
		}

		private void ReloadViewModel(long pOid)
		{
			if (pOid == -1)
			{
				this.Dispatch(
					delegate
					{
						MessageBox.Show("Leider besitzen Sie nicht genügend Lizenzen um einen neuen Benutzer anzulegen!",
							"Benutzer anlegen", MessageBoxButton.OK, MessageBoxImage.Information);
					});
			}
			else
			{
				VMFactory.CreateEmployeeVMAsync(pOid, cb => this.Dispatch(delegate
				{
				    ViewModel = cb;

                    if (ModalEditViewUpdateCallback != null)
                    {
                        ModalEditViewUpdateCallback();
                    }

				    PreselectEmployeeBrush();
				}));
			}

			IsDoneWithInsertOrUpdate = true;
		}

	    private void PreselectEmployeeBrush()
	    {
            if (ViewModel.EmployeeBrush == null)
            {
                return;
            }

            var element118 = ((List<SolidColorBrush>)combobox_brush.ItemsSource).FirstOrDefault(f => f.Color.Equals(ViewModel.EmployeeBrush.Color));
            combobox_brush.SelectedItem = element118;
	    }

	    public void ReloadViewModel()
		{
			ReloadViewModel(ViewModel.DataContract.EmployeeOid.Value);
		}

		private void TabItemAbsenceTimes_Selected(object sender, RoutedEventArgs e)
		{
			if (grid_AbsenceTimes == null)
			{
				grid_AbsenceTimes = rootGrid.Resources["datagrid_absences"] as GridControl;

				//var col = this.grid_AbsenceTimes.Columns["EndDT"];
				//var settings = col.EditSettings;
				//DateEditSettings des = (DateEditSettings)settings;
				//des.DisplayTextConverter = new DateNullValueToEmptyStringConverter();

				GroupBoxAbsenceTimes.Content = grid_AbsenceTimes;

				if (ViewModel.AbsenceTimes != null)
				{
					grid_AbsenceTimes.Columns["Reason"].EditSettings = new ComboBoxEditSettings
					{
						ItemsSource = ViewModel.AbsenceTimes.PossibleReasons
					};
				}
			}
		}

		private void TabItemCustomers_Selected(object sender, RoutedEventArgs e)
		{
			if (grid_Customers == null)
			{
				grid_Customers = rootGrid.Resources["grid_CustomerRelation"] as GridControl;

				GroupBoxCustomers.Content = grid_Customers;
				if (ViewModel.CustomerRelations != null)
				{
					grid_Customers.Columns["Role"].EditSettings = new ComboBoxEditSettings
					{
						ItemsSource = ViewModel.CustomerRelations.PossibleRoles
					};
				}
			}
		}

		private void UserControl_GotFocus(object sender, RoutedEventArgs e)
		{
			if (e.OriginalSource.Equals(this))
			{
				textbox_first.Focus();
			}
		}

		private void button_addAbsence_Click(object sender, RoutedEventArgs e)
		{
			if (ValidationTrigger.Validate(groupbox_newAbsenceTime))
			{
				ViewModel.AbsenceTimes.AddNewVMToList();
			}
		}

		private void button_addCustomerRelation_Click(object sender, RoutedEventArgs e)
		{
			if (ValidationTrigger.Validate(groupbox_newCustomerRel))
			{
				ViewModel.CustomerRelations.AddNewVMToList();
			}
		}

		private void button_addFocus_Click(object sender, RoutedEventArgs e)
		{
			var lFocus = listbox_possibleFocuses.SelectedItem as ValueListEntryDC;
			ViewModel.PossibleFocuses.Remove(lFocus);
			ViewModel.Focuses.Add(lFocus);
			ViewModel.Focuses.Sort();
		}

		private void button_addQualification_Click(object sender, RoutedEventArgs e)
		{
			var lQualification = listbox_possibleQualification.SelectedItem as ValueListEntryDC;
			ViewModel.PossibleQualifications.Remove(lQualification);
			ViewModel.Qualifications.Add(lQualification);
			ViewModel.Qualifications.Sort();
		}

		private void button_removeAbsence_Click(object sender, RoutedEventArgs e)
		{
			ViewModel.AbsenceTimes.VMList.Remove(grid_AbsenceTimes.GetCurrentValue<AbsenceTimeVM>());
			BeWoWpfUtils.RefreshDXGrid(grid_AbsenceTimes);
		}

		private void button_removeCustomerRelation_Click(object sender, RoutedEventArgs e)
		{
			ViewModel.CustomerRelations.VMList.Remove(grid_Customers.GetCurrentValue<CustomerEmployeeRelationVM>());
			BeWoWpfUtils.RefreshDXGrid(grid_Customers);
		}

		private void button_removeFocus_Click(object sender, RoutedEventArgs e)
		{
			var lFocus = listbox_focuses.SelectedItem as ValueListEntryDC;
			ViewModel.Focuses.Remove(lFocus);
			ViewModel.PossibleFocuses.Add(lFocus);
			ViewModel.PossibleFocuses.Sort();
		}

		private void button_removeQualificeation_Click(object sender, RoutedEventArgs e)
		{
			var lQualification = listbox_qualifications.SelectedItem as ValueListEntryDC;
			ViewModel.Qualifications.Remove(lQualification);
			ViewModel.PossibleQualifications.Add(lQualification);
			ViewModel.PossibleQualifications.Sort();
		}

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

		private void tabitem_documents_Selected(object sender, RoutedEventArgs e)
		{
			if (ViewModel.IsNew)
			{
				MessageBox.Show("Bevor zu einem Datensatz Dokumente hinterlegt werden können, muss dieser gespeichert werden.",
					"Erst speichern bitte", MessageBoxButton.OK, MessageBoxImage.Information);
				return;
			}

			if (tabitem_documents.Content == null)
			{
				tabitem_documents.Content = new BeWoFileView(TableID.Employee, ViewModel.DataContract.EmployeeOid.Value);
			}
		}

        private void tabitem_chatservice_Selected(object sender, RoutedEventArgs e)
		{			
			if (tabitem_chatservice.Content == null)
			{
				tabitem_chatservice.Content = new ChatServiceEmployee(TableID.Employee, ViewModel.DataContract.EmployeeOid.Value);
			}
		}

		private void button_addContract_Click(object sender, RoutedEventArgs e)
		{
			ViewModel.Contracts.AddNewVMToList();
			tabcontrol_contracts.SelectedIndex = tabcontrol_contracts.Items.Count - 1;
		}

		private void btn_deleteContract_Click(object sender, RoutedEventArgs e)
		{
			var contract = tabcontrol_contracts.SelectedItem as ContractVM;


			ViewModel.Contracts.VMList.Remove(contract);
		}

		private void TableView_OnRowDoubleClick(object sender, RowDoubleClickEventArgs e)
		{
			var grid_CustomerRelation = (GridControl) rootGrid.Resources["grid_CustomerRelation"];
			var selectedCustomerEmployeeRelationVM =
				grid_CustomerRelation.GetRow(e.HitInfo.RowHandle) as CustomerEmployeeRelationVM;

			if (selectedCustomerEmployeeRelationVM == null || !BeWoApp.LoggedOnUser.HasRight(UserRightType.CustomerView_View))
				return;

			VMFactory.CreateCustomerVMAsync(selectedCustomerEmployeeRelationVM.Customer.CustomerOid,
				cb => this.Dispatch(
					() => BeWoUtils.OpenModalViewWindow<CustomerVM, CustomerDC, EmployeeView>(cb, this, () => this.Dispatch(
						delegate
						{
							CompactCustomerDC customerToUpdate = selectedCustomerEmployeeRelationVM.Customer;

							//ServiceFacade.DoCustomerServiceSync(
							//    s => customerToUpdate = s.GetCompactCustomerDC(customerToUpdate.CustomerOid));

							//foreach (var item in((BindingList<CustomerEmployeeRelationVM>) grid_CustomerRelation.ItemsSource).Where(item => item.Customer.Equals(customerToUpdate)))
							//{
							//    item.Customer = null;
							//    item.Customer = customerToUpdate;
							//}

							//grid_CustomerRelation.RefreshData();

							BeWoUtils.UpdateAllViews(customerToUpdate);
						}))));
		}

		private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
		{
			string emailAddress = (sender as Button).Name.Equals("EMailSendBtn") ? ViewModel.EMail : ViewModel.PrivateEMail;
			BeWoUtils.OpenMailClient(emailAddress);
		}

		private void TabItemOvertimes_Selected(object sender, RoutedEventArgs e)
		{
			if (grid_Overtimes == null)
			{
				grid_Overtimes = rootGrid.Resources["datagrid_overtimes"] as GridControl;

				GroupBoxOvertimes.Content = grid_Overtimes;

				if (ViewModel.AbsenceTimes != null && grid_Overtimes != null)
				{
					grid_Overtimes.Columns["Auszahlungsart"].EditSettings = new ComboBoxEditSettings
					{
						ItemsSource = ViewModel.PossibleAuszahlungsarten
					};
				}
			}
		}

		private void button_addOvertime_Click(object sender, RoutedEventArgs e)
		{
			if (ValidationTrigger.Validate(groupbox_newOvertime))
			{
				ViewModel.Overtimes.AddNewVMToList();
			}
		}

		private void button_removeOvertime_Click(object sender, RoutedEventArgs e)
		{
			ViewModel.Overtimes.VMList.Remove(grid_Overtimes.GetCurrentValue<OvertimeVM>());
			BeWoWpfUtils.RefreshDXGrid(grid_Overtimes);
		}

		private void ChkArchiviert_OnChecked(object sender, RoutedEventArgs e)
		{
			ViewModel.IsArchived = true;
		}

		private void ChkArchiviert_OnUnchecked(object sender, RoutedEventArgs e)
		{
			if (ViewModel.DataContract.ActivationType == ActivationTypeId.Archived)
			{
				var licenseInfo = ServiceFacade.DoOperationsServiceSync(s => s.GetLicenseInfo());

				if (licenseInfo.EmployeeCount >= licenseInfo.MaxEmployeeCount)
				{
					
					MessageBox.Show("Leider verfügen Sie nicht über genügend Lizenzen, um diese/n Mitarbeiter/in aus dem Archiv zu holen.\n\n" +
								string.Format("Sie verfügen derzeit über {0} kostenpflichtige Benutzerlizenzen, somit können Sie maximal {1} Mitarbeiter anlegen.\n({0} Benutzer + {2} % = {1} Mitarbeiterlizenzen).", licenseInfo.MaxLicenseCount, licenseInfo.MaxEmployeeCount, licenseInfo.PercentFreeEmployee) +
								"\n\nSie können nun entweder Mitarbeiter archivieren oder im Modul \"Benutzer\" neue Benutzerlizenzen bestellen. Bitte beachten Sie, dass hierfür das Recht \"Neue Lizenz bestellen\" erforderlich ist.", "Mitarbeiter anlegen", MessageBoxButton.OK,
						MessageBoxImage.Information);

					chkArchiviert.IsChecked = true;
				}
				else
				{
					ViewModel.IsArchived = false;
				}
			}
		}

	    private void Combobox_brush_OnLoaded(object sender, RoutedEventArgs e)
	    {
	        PreselectEmployeeBrush();
	    }


       


	}
}