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

using BeWo.ViewModel;

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

using DevExpress.Data.Linq;

namespace BeWo.Scheduler.ViewModel
{
	public class SchedulerAppointmentVM : AbstractDCMapperVM<SchedulerAppointmentDC>, IBeWoAppointment
	{
		public static string PropertyName_Type           = "Type";
		public static string PropertyName_Start          = "Start";
		public static string PropertyName_End            = "End";
		public static string PropertyName_AllDay         = "AllDay";
		public static string PropertyName_Subject        = "Subject";
		public static string PropertyName_Location       = "Location";
		public static string PropertyName_Status         = "Status";
		public static string PropertyName_RecurrenceInfo = "RecurrenceInfo";
		public static string PropertyName_Description    = "Description";
		public static string PropertyName_EmployeeList   = "EmployeeList";
		public static string PropertyName_CustomerList   = "CustomerList";
		public static string PropertyName_ResourceList   = "ResourceList";
		public static string PropertyName_IsPrivate      = "IsPrivate";
		public static string PropertyName_Originator     = "Originator";

		private bool _AllDay;
		private String _Description;
		private DateTime _End;
		private String _Location;
		private String _RecurrenceInfo;
		private DateTime _Start;
		private int _Status;
		private String _Subject;
		private int _Type;
		private Dictionary<string, object> _CustomFields;
		private bool _IsPrivate;
		private List<Employee2SchedulerAppointmentDC> _EmployeeList;
		private List<CompactCustomerDC> _CustomerList;
		private List<ResourceDC> _ResourceList;
		private CompactEmployeeDC _Originator;

		public object Id { get; set; }
		public int LabelId { get; set; }
		public Dictionary<string, object> CustomFields
		{
			get { return _CustomFields ?? (_CustomFields = new Dictionary<String, object>()); }
			set
			{
				if (!AreDifferent(_CustomFields, value))
				{
				    return;
				}

				_CustomFields = value;

				EmployeeList = (List<Employee2SchedulerAppointmentDC>) value["EmployeeList"];
				CustomerList = (List<CompactCustomerDC>)               value["CustomerList"];
				ResourceList = (List<ResourceDC>)                      value["ResourceList"];
				Originator   = (CompactEmployeeDC)                     value["Originator"];
				IsPrivate    = (bool)                                  value["IsPrivate"];
			}
		}

		public int EventType
		{
			get { return _Type; }
            set
			{
				if (AreDifferent(_Type, value))
				{
					_Type = value;
					StoreDirtyInformation(AreDifferent(DataContract.Type, value), PropertyName_Type);
					FirePropertyChanged(PropertyName_Type);
				}
			}
		}
		public DateTime End
		{
			get { return _End; }
            set
			{
				if (AreDifferent(_End, value))
				{
					_End = value;
					StoreDirtyInformation(AreDifferent(DataContract.EndDate, value), PropertyName_End);
					FirePropertyChanged(PropertyName_End);
				}
			}
		}
		public DateTime Start
		{
			get { return _Start; }
            set
			{
				if (AreDifferent(_Start, value))
				{
					_Start = value;
					StoreDirtyInformation(AreDifferent(DataContract.StartDate, value), PropertyName_Start);
					FirePropertyChanged(PropertyName_Start);
				}
			}
		}
		public bool AllDay
		{
			get { return _AllDay; }
            set
			{
				if (AreDifferent(_AllDay, value))
				{
					_AllDay = value;
					StoreDirtyInformation(AreDifferent(DataContract.AllDay, value), PropertyName_AllDay);
					FirePropertyChanged(PropertyName_AllDay);
				}
			}
		}
		public String Subject
		{
			get { return _Subject; }
            set
			{
				if (AreDifferent(_Subject, value))
				{
					_Subject = value;
					StoreDirtyInformation(AreDifferent(DataContract.Subject, value), PropertyName_Subject);
					FirePropertyChanged(PropertyName_Subject);
				}
			}
		}
		public String Location
		{
			get { return _Location; }
            set
			{
				if (AreDifferent(_Location, value))
				{
					_Location = value;
					StoreDirtyInformation(AreDifferent(DataContract.Location, value), PropertyName_Location);
					FirePropertyChanged(PropertyName_Location);
				}
			}
		}
		public int Status
		{
			get { return _Status; }
            set
			{
				if (AreDifferent(_Status, value))
				{
					_Status = value;
					StoreDirtyInformation(AreDifferent(DataContract.Status, value), PropertyName_Status);
					FirePropertyChanged(PropertyName_Status);
				}
			}
		}
		public String RecurrenceInfo
		{
			get { return _RecurrenceInfo; }
            set
			{
				if (AreDifferent(_RecurrenceInfo, value))
				{
					_RecurrenceInfo = value;
					StoreDirtyInformation(AreDifferent(DataContract.RecurrenceInfo, value), PropertyName_RecurrenceInfo);
					FirePropertyChanged(PropertyName_RecurrenceInfo);
				}
			}
		}
		public String Description
		{
			get { return _Description; }
            set
			{
				if (AreDifferent(_Description, value))
				{
					_Description = value;
					StoreDirtyInformation(AreDifferent(DataContract.Description, value), PropertyName_Description);
					FirePropertyChanged(PropertyName_Description);
				}
			}
		}
		public List<Employee2SchedulerAppointmentDC> EmployeeList
		{
			get { return _EmployeeList ?? (_EmployeeList = new List<Employee2SchedulerAppointmentDC>()); }
			set
			{
				if (AreDifferent(_EmployeeList, value))
				{
					_EmployeeList = value;
					StoreDirtyInformation(AreDifferent(DataContract.EmployeeList, value), PropertyName_EmployeeList);
					FirePropertyChanged(PropertyName_EmployeeList);
				}
			}
		}
		public List<CompactCustomerDC> CustomerList
		{
			get { return _CustomerList ?? (_CustomerList = new List<CompactCustomerDC>()); }
			set
			{
				if (AreDifferent(_CustomerList, value))
				{
					_CustomerList = value;
					StoreDirtyInformation(AreDifferent(DataContract.CustomerList, value), PropertyName_CustomerList);
					FirePropertyChanged(PropertyName_CustomerList);
				}
			}
		}
		public List<ResourceDC> ResourceList
		{
			get { return _ResourceList ?? (ResourceList = new List<ResourceDC>()); }
			set
			{
				if (AreDifferent(_ResourceList, value))
				{
					_ResourceList = value;
					StoreDirtyInformation(AreDifferent(DataContract.ResourceList, value), PropertyName_ResourceList);
					FirePropertyChanged(PropertyName_ResourceList);
				}
			}
		}
		public bool IsPrivate
		{
			get { return _IsPrivate; }
			set
			{
				if (AreDifferent(_IsPrivate, value))
				{
					_IsPrivate = value;
					StoreDirtyInformation(AreDifferent(DataContract.IsPrivate,value), PropertyName_IsPrivate);
					FirePropertyChanged(PropertyName_IsPrivate);
				}
			}
		}
		public CompactEmployeeDC Originator
		{
			get { return _Originator; }
			set
			{
				if (AreDifferent(_Originator, value))
				{
					_Originator = value;
					StoreDirtyInformation(AreDifferent(DataContract.Originator, value), PropertyName_Originator);
					FirePropertyChanged(PropertyName_Originator);
				}
			}
		}
		public virtual TimeSpan EndTime
		{
			get { return End.TimeOfDay; }
            set { }
		}
        public virtual TimeSpan StartTime
		{
			get { return Start.TimeOfDay; }
            set { }
		}

		public SchedulerAppointmentVM(SchedulerAppointmentDC pDC) : base(pDC, pDC.SchedulerAppointmentOid == null) { }

		public void UpdateCustomFields()
		{
			CustomFields = new Dictionary<string, object>
			{
				{"EmployeeList", EmployeeList},
				{"CustomerList", CustomerList},
				{"ResourceList", ResourceList},
				{"Originator",   Originator},
				{"IsPrivate",    IsPrivate}
			};
		}

		protected override void InitByDataContract(SchedulerAppointmentDC pDataContract)
		{
			_AllDay         = pDataContract.AllDay;
			_Description    = pDataContract.Description;
			_End            = pDataContract.EndDate ?? DateTime.Now;
			_Location       = pDataContract.Location;
			_RecurrenceInfo = pDataContract.RecurrenceInfo;
			_Start          = pDataContract.StartDate ?? DateTime.Now;
			_Status         = pDataContract.Status;
			_Subject        = pDataContract.Subject;
			_Type           = pDataContract.Type;
            _IsPrivate      = pDataContract.IsPrivate;
			_Originator     = pDataContract.Originator;
			_CustomerList   = pDataContract.CustomerList;
			_EmployeeList   = pDataContract.EmployeeList;
			_ResourceList   = pDataContract.ResourceList;
		}

		protected override SchedulerAppointmentDC MapToDataContract(SchedulerAppointmentDC pDataContract, bool doCommit)
		{
			pDataContract.AllDay         = _AllDay;
			pDataContract.Description    = _Description;
			pDataContract.EndDate        = _End;
			pDataContract.Location       = _Location;
			pDataContract.RecurrenceInfo = _RecurrenceInfo;
			pDataContract.StartDate      = _Start;
			pDataContract.Status         = _Status;
			pDataContract.Subject        = _Subject;
			pDataContract.Type           = _Type;
            pDataContract.IsPrivate      = _IsPrivate;
			pDataContract.Originator     = _Originator;
			pDataContract.CustomerList   = _CustomerList;
			pDataContract.EmployeeList   = _EmployeeList;
			pDataContract.ResourceList   = _ResourceList;
			
			return pDataContract;
		}

	    public override bool Equals(object pObj)
	    {
	        if (!(pObj is SchedulerAppointmentVM))
	        {
	            return false;
	        }

	        var obj = (SchedulerAppointmentVM) pObj;

	        var customFieldsAreEqual = false;

	        if (CustomFields.Count == obj.CustomFields.Count)
	        {
	            for (var i = 0; i < CustomFields.Count; i++)
	            {
	                switch (i)
	                {
	                    case 0:
	                        var employeeList1    = (List<Employee2SchedulerAppointmentDC>) CustomFields.ElementAt(i).Value;
                            var objEmployeeList1 = (List<Employee2SchedulerAppointmentDC>) obj.CustomFields.ElementAt(i).Value;

	                        customFieldsAreEqual = employeeList1 == null && objEmployeeList1 == null || employeeList1 != null && employeeList1.AreEqual(objEmployeeList1);
	                        break;
	                    case 1:
                            var customerList1    = (List<CompactCustomerDC>) CustomFields.ElementAt(i).Value;
                            var objCustomerList1 = (List<CompactCustomerDC>) obj.CustomFields.ElementAt(i).Value;

	                        customFieldsAreEqual = customerList1 == null && objCustomerList1 == null || customerList1 != null && customerList1.AreEqual(objCustomerList1);
	                        break;
	                    case 2:
	                        var resourceList1    = (List<ResourceDC>) CustomFields.ElementAt(i).Value;
	                        var objResourceList1 = (List<ResourceDC>) obj.CustomFields.ElementAt(i).Value;

	                        customFieldsAreEqual = resourceList1 == null && objResourceList1 == null || resourceList1 != null && resourceList1.AreEqual(objResourceList1);
	                        break;
	                    case 3:
	                        var originator1    = (CompactEmployeeDC) CustomFields.ElementAt(i).Value;
	                        var objOriginator1 = (CompactEmployeeDC) CustomFields.ElementAt(i).Value;

	                        customFieldsAreEqual = originator1 == null && objOriginator1 == null || originator1 != null && originator1.Equals(objOriginator1);
	                        break;
	                    case 4:
	                        var isPrivate1    = Convert.ToBoolean(CustomFields.ElementAt(i).Value);
                            var objIsPrivate1 = Convert.ToBoolean(CustomFields.ElementAt(i).Value);

	                        customFieldsAreEqual = isPrivate1 == objIsPrivate1;
	                        break;
	                }
	            }
	        }

	        var areEqual =
	            AllDay    == obj.AllDay &&
	            IsPrivate == obj.IsPrivate &&
                IsDirty   == obj.IsDirty &&
                IsNew     == obj.IsNew &&
                customFieldsAreEqual &&
                CustomerList.AreEqual(obj.CustomerList) &&
	            Equals(Description, obj.Description) &&
                EmployeeList.AreEqual(obj.EmployeeList) &&
                Equals(End, obj.End) &&
                Equals(EndTime, obj.EndTime) &&
                Equals(Location, obj.Location) &&
                ResourceList.AreEqual(obj.ResourceList) &&
                Equals(RecurrenceInfo, obj.RecurrenceInfo);

	        return areEqual;
	    }

        public override int GetHashCode()
        {
            return DataContract.SchedulerAppointmentOid.HasValue 
                ? GetType().Name.GetHashCode() ^ DataContract.SchedulerAppointmentOid.Value.GetHashCode() 
                : base.GetHashCode();
        }
	}
}
