using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;

using BeWo.Core;
using BeWo.Core.Service;
using BeWo.Validation;

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

namespace BeWo.ViewModel
{
    public class ServiceRecordVM : AbstractDCMapperVM<ServiceRecordDC>
    {
        #region Constants and Fields

        public static string PropertyName_Category = "Category";

        public static string PropertyName_Category2Services = "Category2Services";

		public static string PropertyName_SortedCategories = "SortedCategories";

        public static string PropertyName_CostBearer = "CostBearer";

        public static string PropertyName_Customer = "Customer";

        public static string PropertyName_Date = "Date";

		public static string PropertyName_EditableEndDate = "EditableEndDate";

        public static string PropertyName_Duration = "Duration";

        public static string PropertyName_Employee = "Employee";

        public static string PropertyName_EndTime = "EndTimeEditString";

        public static string PropertyName_GoalTree = "GoalTree";

        public static string PropertyName_GroupEmployeeCount = "GroupEmployeeCount";

        public static string PropertyName_GroupPersonCount = "GroupPersonCount";

        public static string PropertyName_GroupRoundedDuration = "GroupRoundedDuration";

        public static string PropertyName_IsGoalTreeVisible = "IsGoalTreeVisible";

        public static string PropertyName_Notice = "Notice";

        public static string PropertyName_Notice2 = "Notice2";
        
        public static string PropertyName_Notice3 = "Notice3";
        
        public static string PropertyName_Notice4 = "Notice4";

        public static string PropertyName_Notice5 = "Notice5";

        public static string PropertyName_PossibleCostBearers = "PossibleCostBearers";

        public static string PropertyName_PossibleCustomers = "PossibleCustomers";

        public static string PropertyName_PossibleServiceDescriptions = "PossibleServiceDescriptions";

        public static string PropertyName_PossibleSupportConcepts = "PossibleSupportConcepts";

        public static string PropertyName_RoundedDuration = "RoundedDuration";

        public static string PropertyName_SelectedGoals = "SelectedGoals";

        public static string PropertyName_ServiceDescription = "ServiceDescription";

        public static string PropertyName_StartTime = "StartTimeEditString";

        public static string PropertyName_SupportConcept = "SupportConcept";

        public static string PropertyName_ServiceRecordType = "ServiceRecordType";

        public static string PropertyName_IsServiceRecordTypeDefaultActivity = "IsServiceRecordTypeDefaultActivity";

        public static string PropertyName_IsServiceRecordTypeContent = "IsServiceRecordTypeContent";

		public static string PropertyName_DistanceInMeter = "DistanceInMeter";

        private static readonly DateTime NULL_TIME = new DateTime(2000, 1, 1, 0, 0, 1);

        private Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> _Category2Services;

        //private readonly List<SupportConceptTreeNodeDC> _Tree;

        private List<ValueListEntryDC> _AllGoalCategories;

        private List<ValueListEntryDC> _AllGoals;

        private ServiceCategoryDC _Category;

        private FlatSupportConceptTreeNodeDC _ChoosenNode;

        private CompactOrganisationDC _CostBearer;

        private CompactCustomerDC _Customer;

        private DateTime? _Date;

        private bool _DeleteAllowed = true;

        private int? _Duration;

        private bool _EditAllowed = true;

        private CompactEmployeeDC _Employee;

        private DateTime? _EndTime;

		private DateTime? _EditableEndDate;

        private List<SupportConceptGoalDC> _GoalTree;

        private int? _GroupEmployeeCount;

        private long? _GroupOid;

        private long? _SignatureOid;

        private int? _GroupPersonCount;

        private decimal? _GroupRoundedDuration;

        private string _InsUser;

        private DateTime? _InsertedOn;

        private string _Notice;

        private string _Notice2;
        
        private string _Notice3;
        
        private string _Notice4;
        
        private string _Notice5;

        private decimal _RoundedDuration;

        private ObservableSortCollection<ValueListEntryDC> _SelectedGoals;

        private ServiceDescriptionDC _ServiceDescription;

        private DateTime? _StartTime;

        private CompactSupportConceptDC _SupportConcept;

        private ServiceRecordTypeId _ServiceRecordType = ServiceRecordTypeId.DefaultActivity;

        public List<ServiceAccountingDC> _ServiceAccountings;

		private int? _DistanceInMeter;

        #endregion

        #region Constructors and Destructors

        public ServiceRecordVM()
        {
            DataContract = new ServiceRecordDC {Notice = ""};
        }

        public ServiceRecordVM(
            ServiceRecordDC pDC,
            Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> pCategory2Services,
            List<ValueListEntryDC> pAllGoalCategories,
            List<ValueListEntryDC> pAllGoals)
            : base(pDC, pDC.ServiceRecordOid == null)
        {
            _Category2Services = pCategory2Services;

            ChangeGoalTree(pAllGoalCategories, pAllGoals);
        }

        #endregion

        #region Properties
		
		public int? DistanceInMeter
        {
			get { return _DistanceInMeter; }

            set
            {
				if (AreDifferent(_DistanceInMeter, value))
                {
					_DistanceInMeter = value;
                    StoreDirtyInformation(AreDifferent(DataContract.DistanceInMeter, value), PropertyName_DistanceInMeter);
					FirePropertyChanged(PropertyName_DistanceInMeter);
                }
            }
        }

        public decimal AssistanceDuration
        {
            get
            {
                if (GroupOid != null)
                {
                    return RoundedDuration;
                }

                if (_Duration != null)
                {
                    return Duration.Value;
                }

                return 0;
            }
        }

        public Brush BackgroundBrush
        {
            get
            {
                Brush brush = null;
                if (_GroupOid != null)
                {
                    brush = Application.Current.FindResource("GroupBookingBackgroundBrush") as Brush;
                }

                return brush ?? Brushes.White;
                }
            }

        public String CategoryString
        {
            get { return _Category != null ? _Category.ToString() : null; }
        }

        public String ServiceDescriptionString
        {
            get { return _ServiceDescription != null ? _ServiceDescription.ToString() : null; }
        }
		
		public List<ValueListEntryDC> AllGoalCategories
        {
			get { return _AllGoalCategories; }

            set { _AllGoalCategories = value; }
        }

		public List<ValueListEntryDC> AllGoals
		{
			get { return _AllGoals; }

			set { _AllGoals = value; }
		}

		public ServiceCategoryDC Category
		{
			get { return _Category; }

			set
			{
				if (AreDifferent(_Category, value))
				{
					_Category = value;
					ServiceDescription = null;
					FirePropertyChanged(PropertyName_Category);
					FirePropertyChanged(PropertyName_PossibleServiceDescriptions);
				}
			}
		}

        public Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> Category2Services
        {
            get { return _Category2Services; }
            set
            {
                _Category2Services = value;
                FirePropertyChanged(PropertyName_Category2Services);
				FirePropertyChanged(PropertyName_SortedCategories);
				FirePropertyChanged(PropertyName_PossibleServiceDescriptions);
            }
        }

		public IList<ServiceCategoryDC> SortedCategories
		{
			get
			{
                return Category2Services != null ? Category2Services.Keys.OrderBy(cat => cat.Position).ToList() : null;
			}
		}

        public FlatSupportConceptTreeNodeDC ChoosenNode
        {
            get { return _ChoosenNode; }

            set
            {
                _ChoosenNode = value;

                if (value != null)
                {
                    if (value.SupportConceptTreeNodeDC != null)
                    {
                        if (Employee == null)
                        {
                            Employee = value.SupportConceptTreeNodeDC.Employee;
                        }

                        Customer       = value.SupportConceptTreeNodeDC.Customer;
                        SupportConcept = value.SupportConceptTreeNodeDC.SupportConcept;
                        CostBearer     = value.SupportConceptTreeNodeDC.CostBearer;
                    }
                }
                else
                {
                    Employee       = null;
                    Customer       = null;
                    SupportConcept = null;
                    CostBearer     = null;
                }
            }
        }

        public CompactOrganisationDC CostBearer
        {
            get { return _CostBearer; }

            set
            {
                if (AreDifferent(_CostBearer, value))
                {
                    _CostBearer = value;
                    StoreDirtyInformation(!AreEqual(DataContract.CostBearer, value), PropertyName_CostBearer);
                    FirePropertyChanged(PropertyName_CostBearer);
                    FirePropertyChanged(PropertyName_RoundedDuration);
                }
            }
        }

        [Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
        public CompactCustomerDC Customer
        {
            get { return _Customer; }

            set
            {
                if (AreDifferent(_Customer, value))
                {
                    _Customer = value;
                    StoreDirtyInformation(!AreEqual(DataContract.Customer, value), PropertyName_Customer);
                    FirePropertyChanged(PropertyName_Customer);
                }
            }
        }

        [Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
        public DateTime? Date
        {
            get { return _Date; }

            set
            {
                if (AreDifferent(_Date, value))
                {
                    _Date = value;
                    TimeCheck();
					if (BeWoApp.AppSettings.IsEndDateVisible)
					{
						if (value > EditableEndDate)
						{
							EditableEndDate = value;
						}
					}
                    FirePropertyChanged(PropertyName_Date);
                }
            }
        }

        public DateTime? DateAndTime
        {
            get
            {
                var date = _Date;
                var time = _StartTime;

                if (date != null && time != null)
                {
                    date = date.Value.AddHours(time.Value.Hour);
                    date = date.Value.AddMinutes(time.Value.Minute);
                    date = date.Value.AddSeconds(time.Value.Second);
                }

                return date;
            }
        }

        public DateTime? StartDate
        {
            get { return DateAndTime; }
        }
        
        public DateTime? StartMinutes
        {
            get { return StartDate.HasValue && StartDate.Value.Second == 0 ? StartDate : null; }
        }

        public DateTime? EndMinutes
        {
            get { return EndDate.HasValue && EndDate.Value.Second == 0 ? EndDate : null; }
        }

        public DateTime? EndDate
        {
            get
            {
                var dt = DateAndTime;
                if (dt.HasValue)
                {
                    if (_StartTime != null)
                    {
                        var timeDt = _StartTime.Value;

                        if (GroupOid != null && GroupRoundedDuration != null)
                        {
                            dt = timeDt.AddMinutes((double) GroupRoundedDuration);
                        }
                        else
                        {
                            dt = timeDt.AddMinutes((double) RoundedDuration);
                        }
                    }
                }

                return dt;
            }
        }

        public String Id
        {
            get { return String.Format("{0}", DataContract.ServiceRecordOid); }
        }

        [Validation(ValidationRule = ValidationRules.GreaterThanOrEqualZero)]
        public int? Duration
        {
            get { return _Duration; }

            set
            {
                if (value >= 0 && AreDifferent(_Duration, value))
                {
                        Console.WriteLine("Change Duration " + value.Value);

                    _Duration = value;

                    if (StartTime != null )
                    {
						//if (BeWoApp.AppSettings.IsEndDateVisible)
						//{
						//	if (EditableEndDate == null)
						//	{
						//		EditableEndDate = Date;
						//	}

						//	EndTime = EditableEndDate.Value.AddMinutes(value.Value);
						//}
						//else
						//{
							EndTime = StartTime.Value.AddMinutes(value.Value);
						//}
                    }

					if (BeWoApp.AppSettings.IsEndDateVisible)
					{
						//if (Date != null && EndTime != null && Date.Value.Date != EndTime.Value.Date)
						//{

						//	if (StartTime.Value.Hour != 0 && EndTime.Value.Hour != 0)
						//	{
						//		value = (EndTime.Value.Date - Date.Value.Date).GetTotalMinutes();
						//		_Duration += value;
						//	}
						//}
					}

                    TimeCheck();
                    FirePropertyChanged(PropertyName_Duration);
                    FirePropertyChanged(PropertyName_RoundedDuration);
                }

                if (value < 0)
                {
                    Console.WriteLine("Kleiner 0");
                }
            }
        }

        public string DurationAndRoundedDuration
        {
            get
            {
                var rd = BeWoWpfUtils.GetDecimalValueWithMaxDecimal(RoundedDuration, 2);

                if (Category != null && Category.Percentage > 0 && Category.Percentage < 100)
                {
                    rd = (rd*Category.Percentage)/100;
                }

                var strResult = _GroupOid != null ? String.Format("{0} ({0})", rd) : String.Format("{0} ({1})", Duration, rd);

                return strResult;
            }
        }
        
        public bool EditAllowed
        {
            get
            {
                var allowed = false;

                if (BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecordView_Edit))
                {
                    allowed = true;
                }
                else if (BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowChangeWithin24Hours))
                {
                    if (_InsertedOn != null)
                    {
                        if (DateTime.Now < _InsertedOn.Value.AddDays(1))
                        {
                            allowed = true;
                        }
                    }
                }

                if (allowed && BeWoApp.AppSettings.MaxDaysEditServiceRecordsAllowed > 0)
                {
                    if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowEditAfterMaxDaysInNextMonth))
                    {
                        if (Date != null)
                        {
                            var dt = new DateTime(Date.Value.Year, Date.Value.Month, 1);
                            dt = dt.AddMonths(1);
                            dt = dt.AddDays(BeWoApp.AppSettings.MaxDaysEditServiceRecordsAllowed);
                            if (DateTime.Now >= dt)
                            {
                                allowed = false;
                            }
                        }
                    }
                }

	            if (allowed && !BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowEditForOtherEmployees))
	            {
                    if (BeWoApp.LoggedOnEmployee.EmployeeOid != Employee.EmployeeOid)
			            allowed = false;
	            }
				if (allowed && GroupOid.HasValue)
				{
					if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowCreatingGroupBooking))
					{
						allowed = false;
					}
				}
				if (allowed && BeWoApp.AppSettings.AnzTageZeiterfassErfolgt > 0)
				{
					if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecordAllowEditAfterMindays))
					{
						if (Date != null)
						{
							var dt = new DateTime(Date.Value.Year, Date.Value.Month, Date.Value.Day);
							dt = dt.AddDays(BeWoApp.AppSettings.AnzTageZeiterfassErfolgt + 1);
							if (DateTime.Now >= dt)
							{
								allowed = false;
							}
						}
					}
				}
                return _EditAllowed && allowed;
            }

            set { _EditAllowed = value; }
        }

        public bool DeleteAllowed
        {
            get
            {
                var allowed = false;
                if (BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecordView_Delete))
                {
                    allowed = true;
                }
                else if (BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowChangeWithin24Hours))
                {
                    if (_InsertedOn != null)
                    {
                        if (DateTime.Now < _InsertedOn.Value.AddDays(1))
                        {
                            allowed = true;
                        }
                    }
                }

                if (allowed && BeWoApp.AppSettings.MaxDaysEditServiceRecordsAllowed > 0)
                {
                    if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowEditAfterMaxDaysInNextMonth))
                    {
                        if (Date != null)
                        {
                            var dt = new DateTime(Date.Value.Year, Date.Value.Month, 1);
                            dt = dt.AddMonths(1);
                            dt = dt.AddDays(BeWoApp.AppSettings.MaxDaysEditServiceRecordsAllowed);
                            if (DateTime.Now >= dt)
                            {
                                allowed = false;
                            }
                        }
                    }
                }
				if (allowed && BeWoApp.AppSettings.AnzTageZeiterfassErfolgt > 0)
				{
					if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecordAllowEditAfterMindays))
					{
						if (Date != null)
						{
							var dt = new DateTime(Date.Value.Year, Date.Value.Month, Date.Value.Day);
							dt = dt.AddDays(BeWoApp.AppSettings.AnzTageZeiterfassErfolgt + 1);
							if (DateTime.Now >= dt)
							{
								allowed = false;
							}
						}
					}
				}
				if (allowed && !BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowEditForOtherEmployees))
				{
                    if (BeWoApp.LoggedOnEmployee.EmployeeOid != Employee.EmployeeOid)
						allowed = false;
				}
				if (allowed && GroupOid.HasValue)
				{
					if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_AllowCreatingGroupBooking))
					{
						allowed = false;
					}
				}
                return _DeleteAllowed && allowed;
            }

            set { _DeleteAllowed = value; }
        }

        public static bool IsHistoryAllowed
		{
            get { return BeWoApp.LoggedOnUser.HasRight(UserRightType.ServiceRecord_ShowHistory); }
			}

        [Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
        public CompactEmployeeDC Employee
        {
            get { return _Employee; }

            set
            {
                if (AreDifferent(_Employee, value))
                {
                    _Employee = value;

                    StoreDirtyInformation(!AreEqual(DataContract.Employee, value), PropertyName_Employee);
                    FirePropertyChanged(PropertyName_Employee);
                }
            }
        }

        public string EmployeeName
        {
            get
            {
                if (_Employee != null)
                {
                    return _Employee.FirstName + " " + _Employee.LastName;
                }
                    return string.Empty;
                }
            }

        public String EndTimeEditString
        {
            get
            {
                if (_EndTime == null || _EndTime.Value.Second != 0)
                { 
                    return null;
                }
                return String.Format("{0:HH:mm}", _EndTime);
            }

            set
            {
				if (String.IsNullOrEmpty(value))
					EndTime = null;
				else
				{
					if (BeWoApp.AppSettings.IsEndDateVisible)
					{
						DateTime? endTime = EditableEndDate;
						
						String dtStr = String.Format("{0:dd.MM.yyyy} {1}", endTime, value);
						DateTime dt;


						if (DateTime.TryParse(dtStr, out dt))
							EndTime = dt;
						else
							EndTime = null;
					}
					else
					{
						DateTime? endTime = EndTime;
						if (!endTime.HasValue)
							endTime = EndDate;
						if (!endTime.HasValue)
							endTime = DateTime.Now;

						String dtStr = String.Format("{0:dd.MM.yyyy} {1}", endTime, value);
						DateTime dt;


						if (DateTime.TryParse(dtStr, out dt))
							EndTime = dt;
						else
							EndTime = null;
					}
				}
            }
        }

		public DateTime? EditableEndDate
        {
            get {

                if (BeWoApp.AppSettings.IsEndDateVisible)
                {
					return _EditableEndDate;
                }
                return null;
			}

            set
            {
				if (BeWoApp.AppSettings.IsEndDateVisible)
                {
					_EditableEndDate = value;
					if (value < Date)
					{
						Date = value;
					}
					FirePropertyChanged(PropertyName_EditableEndDate);
                }
            }
        }
        
        public DateTime? EndTime
        {
            get {

                if (BeWoApp.AppSettings.IsEndDateVisible)
                {
                    if (!_EndTime.HasValue )
                        return DateTime.Now.Date;
                    else
                        return _EndTime;
                }
                else
                    return _EndTime; 
            }

            set
            {
				bool cont = (_EndTime == null && value != null) || (_EndTime != null && value == null) || (_EndTime != null && _EndTime.Value.TimeOfDay != value.Value.TimeOfDay);

				//if (BeWoApp.AppSettings.IsEndDateVisible)
				//{
				//	cont = (_EndTime == null && value != null) || (_EndTime != null && value == null) || (_EndTime != null && _EndTime.Value.TimeOfDay != value.Value.TimeOfDay) || (value != null && _EndTime != null);
				//}
                if (cont)
                {
                    if (value != null)
                    {
                        Console.WriteLine("Change EndTime " + value.Value.ToShortTimeString());
                    }

                    _EndTime = value;

                    if (_EndTime != null)
                    {
						if (BeWoApp.AppSettings.IsEndDateVisible)
						{
							if (_StartTime.Value.Second != 0)
							{
								StartTime = new DateTime(StartTime.Value.Year, StartTime.Value.Month, StartTime.Value.Day, StartTime.Value.Hour, 0, 0);
							}

							var start = new DateTime(StartTime.Value.Year, StartTime.Value.Month, StartTime.Value.Day, StartTime.Value.Hour, StartTime.Value.Minute, 0);

							var diff = _EndTime.Value.Subtract(start);

							Duration = (int)diff.TotalMinutes;
						}
						else
						{
							if (_StartTime.Value.Second != 0)
							{
								StartTime = new DateTime(_EndTime.Value.Year, _EndTime.Value.Month, _EndTime.Value.Day, _EndTime.Value.Hour, 0, 0);
							}

							var start = new DateTime(_EndTime.Value.Year, _EndTime.Value.Month, _EndTime.Value.Day, StartTime.Value.Hour, StartTime.Value.Minute, 0);

							var diff = _EndTime.Value.Subtract(start);

							Duration = (int)diff.TotalMinutes;
						}
                    }
					//TimeCheck();
                    FirePropertyChanged(PropertyName_EndTime);
                }
            }
        }

        public List<SupportConceptGoalDC> GoalTree
        {
            get { return _GoalTree; }

            set
            {
                _GoalTree = value;
                FirePropertyChanged(PropertyName_GoalTree);
                FirePropertyChanged(PropertyName_IsGoalTreeVisible);
            }
        }

        public int? GroupEmployeeCount
        {
            get { return _GroupEmployeeCount; }

            set
            {
                if (AreDifferent(_GroupEmployeeCount, value))
                {
                    _GroupEmployeeCount = value;
                    StoreDirtyInformation(AreDifferent(DataContract.GroupEmployeeCount, value), PropertyName_GroupEmployeeCount);
                    FirePropertyChanged(PropertyName_GroupEmployeeCount);
                }
            }
        }

        public long? GroupOid
        {
            get { return _GroupOid; }

            set { _GroupOid = value; }
        }

        public long? SignatureOid
        {
            get { return _SignatureOid; }

            set { _SignatureOid = value; }
        }

        public int? GroupPersonCount
        {
            get { return _GroupPersonCount; }

            set
            {
                if (AreDifferent(_GroupPersonCount, value))
                {
                    _GroupPersonCount = value;
                    StoreDirtyInformation(AreDifferent(DataContract.GroupPersonCount, value), PropertyName_GroupPersonCount);
                    FirePropertyChanged(PropertyName_GroupPersonCount);
                }
            }
        }

        public decimal? GroupRoundedDuration
        {
            get { return _GroupRoundedDuration; }

            set
            {
                if (AreDifferent(_GroupRoundedDuration, value))
                {
                    _GroupRoundedDuration = value;
                    StoreDirtyInformation(AreDifferent(DataContract.GroupRoundedDuration, value), PropertyName_GroupRoundedDuration);
                    FirePropertyChanged(PropertyName_GroupRoundedDuration);
                }
            }
        }

        public int Index { get; set; }

        public string InsUser
        {
            get { return _InsUser; }

            set { _InsUser = value; }
        }

        public string InsertedOn
        {
            get
            {
                if (_InsertedOn != null)
                {
                    return _InsertedOn.Value.ToShortDateString() + " " + _InsertedOn.Value.ToShortTimeString();
                }

                return null;
            }
        }

        public bool IsGoalTreeVisible
        {
            get { return _GoalTree != null && _GoalTree.Count > 0; }
        }

        public string LongDateString
        {
            get
            {
                var date = string.Empty;

                if (_Date != null)
                {
                    date = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedDayName(_Date.Value.DayOfWeek) + ", " + _Date.Value.ToShortDateString();
                }

                string time = string.Empty;

                if (_StartTime != null)
                {
                    var timeDt = _StartTime.Value;

                    if (timeDt.Second == 0)
                    {
                        time = timeDt.ToShortTimeString();
                        if (GroupOid != null && GroupRoundedDuration != null)
                        {
                            timeDt = timeDt.AddMinutes((double) GroupRoundedDuration);
                        }
                        else
                        {
                            timeDt = timeDt.AddMinutes((double) RoundedDuration);
                        }

                        time = time + " - " + timeDt.ToShortTimeString();
                    }
                }

                date += " " + time;

                if (GroupOid != null && GroupPersonCount != null && GroupRoundedDuration != null)
                {
                    date += "   Gruppe (" + GroupPersonCount.Value + " Teilnehmer, " + GroupEmployeeCount.Value + " Betreuer). Dauer: " +
                            BeWoWpfUtils.GetDecimalValueWithMaxDecimal(GroupRoundedDuration.Value, 2) + " Minuten.";
                }

                return date;
            }
        }

        public Brush MouseOverBackgroundBrush
        {
            get
            {
                Brush brush = null;
                if (_GroupOid != null)
                {
                    brush = Application.Current.FindResource("GroupBookingMouseOverBackgroundBrush") as Brush;
                }

                return brush ?? new SolidColorBrush(Color.FromArgb(0xFF, 0xCC, 0xE0, 0xFF));
            }
        }

        [Validation(ValidationRule = ValidationRules.EmptyNoticeInNewServiceRecordsAllowed)]
        public string Notice
        {
            get { return _Notice; }

            set
            {
                if (AreDifferent(_Notice, value))
                {
                    _Notice = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Notice, value), PropertyName_Notice);
                    FirePropertyChanged(PropertyName_Notice);
                }
            }
        }

        public string Notice2
        {
            get { return _Notice2; }

            set
            {
                if (AreDifferent(_Notice2, value))
                {
                    _Notice2 = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Notice2, value), PropertyName_Notice2);
                    FirePropertyChanged(PropertyName_Notice2);
                }
            }
        }
  
        public string Notice3
        {
            get { return _Notice3; }

            set
            {
                if (AreDifferent(_Notice3, value))
                {
                    _Notice3 = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Notice3, value), PropertyName_Notice3);
                    FirePropertyChanged(PropertyName_Notice3);
                }
            }
        }

        public string Notice4
        {
            get { return _Notice4; }

            set
            {
                if (AreDifferent(_Notice4, value))
                {
                    _Notice4 = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Notice4, value), PropertyName_Notice4);
                    FirePropertyChanged(PropertyName_Notice4);
                }
            }
        }

        public string Notice5
        {
            get { return _Notice5; }

            set
            {
                if (AreDifferent(_Notice5, value))
                {
                    _Notice5 = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Notice5, value), PropertyName_Notice5);
                    FirePropertyChanged(PropertyName_Notice5);
                }
            }
        }

        public List<ServiceDescriptionDC> PossibleServiceDescriptions
        {
            get
            {
                if (_Category == null)
                {
                    return null;
                }

                return _Category2Services.ContainsKey(_Category) ? _Category2Services[_Category] : null;
            }
        }

        public decimal RoundedDuration
        {
            get { return _RoundedDuration; }

            set { _RoundedDuration = value; }
            }

        public Brush SelectedBackgroundBrush
        {
            get
            {
                Brush brush = null;
                if (_GroupOid != null)
                {
                    brush = Application.Current.FindResource("GroupBookingSelectedBackgroundBrush") as Brush;
                }

                return brush ?? new SolidColorBrush(Color.FromArgb(0xFF, 0x93, 0xBC, 0xFF));
                }
            }

        public bool HasGoals
        {
            get { return SelectedGoals.Count > 0; }
        }

        public String GoalString
        {
            get
            {
                var goals = "";

                foreach (var goal in SelectedGoals)
                {
                    if (goals.Length > 0)
                        goals += ", ";
                    goals += goal.TypeDescription;
                }

                return goals;
            }
        }

        public ObservableSortCollection<ValueListEntryDC> SelectedGoals
        {
            get
            {
                return _SelectedGoals ?? (_SelectedGoals = new ObservableSortCollection<ValueListEntryDC>(Comparer.ValueListEntryDCComparer));
            }
        }

        [Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
        public ServiceDescriptionDC ServiceDescription
        {
            get { return _ServiceDescription; }

            set
            {
                if (AreDifferent(_ServiceDescription, value))
                {
                    _ServiceDescription = value;
                    StoreDirtyInformation(!AreEqual(DataContract.ServiceDescription, value), PropertyName_ServiceDescription);
                    FirePropertyChanged(PropertyName_ServiceDescription);
                }
            }
        }

        public string ShortDateString
        {
            get
            {
                var date = string.Empty;

                if (_Date != null)
                {
                    date = _Date.Value.ToShortDateString();
                }

                return date;
            }
        }

        public string ShortNotice
        {
            get
            {
                var desc = Notice;

                if (desc.IndexOf("\r\n") > 0)
                {
                    desc = desc.Substring(0, desc.IndexOf("\r\n"));
                }

                return desc;
            }
        }

        public string ShortTimeString
        {
            get
            {
                var str = string.Empty;

                if (_StartTime != null && _StartTime.Value.Second == 0)
                {
                    str = _StartTime.Value.ToShortTimeString();
                }

                return str;
            }
        }

        public String StartTimeEditString
        {
            get
            {
                if (_StartTime == null || _StartTime.Value.Second != 0)
                {
                    return null;
                }

                return String.Format("{0:HH:mm}", _StartTime);
            }

            set
            {
                if (String.IsNullOrEmpty(value))
                    StartTime = null;
                else
                {
                    var startTime = StartTime;

                    if (!startTime.HasValue)
                    {
                        startTime = StartDate;
                    }

                    if (!startTime.HasValue)
                    {
                        startTime = DateTime.Now;
                    }

                    var dtStr = String.Format("{0:dd.MM.yyyy} {1}", startTime, value);
                    DateTime dt;
                    if (DateTime.TryParse(dtStr, out dt))
                    {
                        StartTime = dt;
                    }
                    else
                    {
                        StartTime = null;
                }
            }
        }
        }

        public DateTime? StartTime
        {
            get
            {
                return _StartTime.Value.Second != 0 ? null : _StartTime;
            }

            set
            {
                DateTime? newStartTime = value ?? NULL_TIME;

                Console.WriteLine("Change StartTime " + newStartTime.Value.ToShortTimeString());
                if ((_StartTime == null && newStartTime != NULL_TIME) ||
                    (_StartTime != null && _StartTime.Value.TimeOfDay != newStartTime.Value.TimeOfDay))
                {
                    _StartTime = newStartTime;

                    if (_StartTime.Value.Second == 0)
                    {
                        if (_EndTime != null)
                        {
                            var end = new DateTime(_StartTime.Value.Year, _StartTime.Value.Month, _StartTime.Value.Day,
                                                    _EndTime.Value.Hour, _EndTime.Value.Minute, 0);

                            var diff = end.Subtract(_StartTime.Value);
                            
                            if (diff.TotalSeconds < 0)
                            {
                                EndTime = _StartTime;
                                end = EndTime.Value;
                            }

                            diff = end.Subtract(_StartTime.Value);
                            Duration = (int) diff.TotalMinutes;
                        }
                        else if (Duration != null)
                        {
                            EndTime = _StartTime.Value.AddMinutes(Duration.Value);
                        }
                    }

                    TimeCheck();
                    FirePropertyChanged(PropertyName_StartTime);
                }
            }
        }

        public CompactSupportConceptDC SupportConcept
        {
            get { return _SupportConcept; }

            set
            {
                if (AreDifferent(_SupportConcept, value))
                {
                    _SupportConcept = value;
                    CostBearer = null;
                    StoreDirtyInformation(!AreEqual(DataContract.SupportConcept, value), PropertyName_SupportConcept);
                    FirePropertyChanged(PropertyName_SupportConcept);
                    FirePropertyChanged(PropertyName_PossibleCostBearers);
                }
            }
        }

        public ServiceRecordTypeId ServiceRecordType
        {
            get { return _ServiceRecordType; }

            set
            {
                if (AreDifferent(_ServiceRecordType, value))
                {
                    _ServiceRecordType = value;

                    StoreDirtyInformation(!AreEqual(DataContract.ServiceRecordType, value), PropertyName_ServiceRecordType);
                    FirePropertyChanged(PropertyName_ServiceRecordType);
                    FirePropertyChanged(PropertyName_IsServiceRecordTypeContent);
                    FirePropertyChanged(PropertyName_IsServiceRecordTypeDefaultActivity);
                }
            }
        }

        public bool IsServiceRecordTypeContent
        {
            get { return ServiceRecordType == ServiceRecordTypeId.Content; }

            set { ServiceRecordType = value ? ServiceRecordTypeId.Content : ServiceRecordTypeId.DefaultActivity; }
            }

        public bool IsServiceRecordTypeDefaultActivity
        {
            get { return ServiceRecordType == ServiceRecordTypeId.DefaultActivity; }

            set { ServiceRecordType = value ? ServiceRecordTypeId.DefaultActivity : ServiceRecordTypeId.Content; }
            }

        #endregion

        #region Public Methods

        public void ChangeGoalTree(List<ValueListEntryDC> goalCats, List<ValueListEntryDC> goals) //, List<ValueListEntryDC> goalsAndCats)
        {
            _AllGoalCategories = goalCats;
            _AllGoals = goals;

            var newList = new List<ValueListEntryDC>();

            if (_AllGoalCategories != null)
            {
                newList.AddRange(_AllGoalCategories);
            }

            if (_AllGoals != null)
            {
                newList.AddRange(_AllGoals);
            }

            GoalTree = SupportConceptService.CreateGoalTree(newList, SelectedGoals);
        }

        public void UpdateServiceAccountings(List<ServiceAccountingDC> serviceAccountings, Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> allDict, bool hilfeplanAusgewaehlt)
        {
            _ServiceAccountings = serviceAccountings;
            var newCategoryDict = new Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>>();

			foreach (var cat in allDict.Keys)
			{
				bool add = true;
				if (hilfeplanAusgewaehlt && cat.OhneHilfeplan.HasValue && cat.OhneHilfeplan.Value == AccountingvisibilityType.NichtKlientenbezogen)
				{
					add = false;
				}
				else if (!hilfeplanAusgewaehlt && cat.OhneHilfeplan.HasValue && cat.OhneHilfeplan.Value == AccountingvisibilityType.NurKlientenbezogen)
				{
					add = false;
				}
				if (add)
				{
					newCategoryDict.Add(cat, allDict[cat]);
				}
			}
			
            ServiceCategoryDC firstCat = null;
            if (_ServiceAccountings != null && allDict != null)
            {
                var globalServices     = _ServiceAccountings.FindAll(sa => sa.ServiceDescription.ScopeType == ScopeTypeId.Global);
                var individualServices = _ServiceAccountings.FindAll(sa => sa.ServiceDescription.ScopeType == ScopeTypeId.Individual);

                if (globalServices.Count > 0)
                {
                    newCategoryDict = new Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>>();
                    foreach (var cat in allDict.Keys)
                    {
                        var sdList    = allDict[cat];
                        var newSdList = sdList.Where(sd => globalServices.Exists(sa => sa.ServiceDescription.Equals(sd))).ToList();

                        if (newSdList.Count > 0)
                        {
							if (firstCat == null || cat.Position < firstCat.Position)
								firstCat = cat;

							newCategoryDict.Add(cat, newSdList);
                        }
                    }
                }
                if (individualServices.Count > 0)
                {
                    newCategoryDict.Add(individualServices[0].ServiceDescription.Category,
                                        individualServices.Select(sa => sa.ServiceDescription).ToList());
                }
            }
            Category2Services = newCategoryDict;
            
            if (Category == null)
                Category = firstCat;
        }

        public ServiceRecordVM Clone()
        {
            var dc = new ServiceRecordDC();

            return new ServiceRecordVM(CopyToDataContract(dc), _Category2Services, _AllGoalCategories, _AllGoals);
        }

        public void CopyTo(ServiceRecordVM copy)
        {
            copy.Notice               = Notice;
            copy.Notice2              = Notice2;
            copy.Notice3              = Notice3;
            copy.Notice4              = Notice4;
            copy.Notice5              = Notice5;
            copy.StartTime            = StartTime;
            copy.EndTime              = EndTime;
            copy.Date                 = Date;
            copy.Duration             = Duration;
            copy.RoundedDuration      = RoundedDuration;
            copy.ServiceRecordType    = ServiceRecordType;
            copy.DistanceInMeter      = DistanceInMeter;
            copy.Employee             = Employee;
            copy.Customer             = Customer;
            copy.SupportConcept       = SupportConcept;
            copy.CostBearer           = CostBearer;
            copy.Category             = Category;
            copy.ServiceDescription   = ServiceDescription;
            copy.GroupEmployeeCount   = GroupEmployeeCount;
            copy.GroupPersonCount     = GroupPersonCount;
            copy.GroupOid             = GroupOid;
            copy.GroupRoundedDuration = GroupRoundedDuration;

            copy.SelectedGoals.Clear();
            foreach (var item in SelectedGoals)
            {
                copy.SelectedGoals.Add(item);
            }

            copy.GoalTree = GoalTree;
        }

        public void SetInsertedOn(DateTime dt)
        {
            _InsertedOn = dt;
        }

        public override string ToString()
        {
            return _Customer + ": " + _Date.Value.ToLongDateString() + string.Format("-  Dauer: {0:0.00} min", RoundedDuration);
        }

        #endregion

        #region Methods

        protected override void InitByDataContract(ServiceRecordDC pDataContract)
        {
            if (pDataContract.ServiceDescription != null)
            {
                _Date = pDataContract.Start.Value.Date;
                
                _StartTime = pDataContract.Start.Value;

                //if (pDataContract.Start.Value.Date == pDataContract.End.Value.Date)
                //{
                //    _Duration = (pDataContract.End.Value - pDataContract.Start.Value).GetTotalMinutes();
                //    if (pDataContract.Start != null && pDataContract.Start.Value.Second == 0 && _Duration != null)
                //    {
                //        _EndTime = pDataContract.Start.Value.AddMinutes(_Duration.Value);
                //    }
                //}

                _Duration = (pDataContract.End.Value - pDataContract.Start.Value).GetTotalMinutes();

               if (pDataContract.Start != null && pDataContract.Start.Value.Second == 0 && _Duration != null)
                {
					if (BeWoApp.AppSettings.IsEndDateVisible)
					{
						if (pDataContract.Start.Value.Date == pDataContract.End.Value.Date)
							_EndTime = pDataContract.Start.Value.AddMinutes(_Duration.Value);
						else
						{
							if (pDataContract.Start.Value.Date != pDataContract.End.Value.Date)
								_EndTime = pDataContract.End.Value;

						}
					}
					else
					{
						_EndTime = pDataContract.Start.Value.AddMinutes(_Duration.Value);
					}
                }
                
                _Notice = pDataContract.Notice;
                _Notice2 = pDataContract.Notice2;
                _Notice3 = pDataContract.Notice3;
                _Notice4 = pDataContract.Notice4;
                _Notice5 = pDataContract.Notice5;
                _ServiceDescription = pDataContract.ServiceDescription;
                _Employee = pDataContract.Employee;
                _Customer = pDataContract.Customer;
                _SupportConcept = pDataContract.SupportConcept;
                _CostBearer = pDataContract.CostBearer;
                _ServiceDescription = pDataContract.ServiceDescription;
                _Category = pDataContract.ServiceDescription.Category;
                _RoundedDuration = pDataContract.RoundedDuration;             
                _InsertedOn = pDataContract.InsertedOn;
                _InsUser = pDataContract.InsUser;
                _GroupEmployeeCount = pDataContract.GroupEmployeeCount;
                _GroupPersonCount = pDataContract.GroupPersonCount;
                _GroupRoundedDuration = pDataContract.GroupRoundedDuration;
                _GroupOid = pDataContract.GroupOid;
                _ServiceRecordType = pDataContract.ServiceRecordType;
                _DistanceInMeter = pDataContract.DistanceInMeter;

                if (pDataContract.Goals != null)
                {
                    _SelectedGoals = new ObservableSortCollection<ValueListEntryDC>(pDataContract.Goals, Comparer.ValueListEntryDCComparer);
                }

                SelectedGoals.CollectionChanged += (s, e) => StoreDirtyInformation(!SelectedGoals.ContainsSameItemsAs(pDataContract.Goals), PropertyName_SelectedGoals);
            }
            else
            {
                _Date = DateTime.Now.Date;
				_EditableEndDate = DateTime.Now.Date;
                _StartTime = NULL_TIME;
                _Duration = null;
            }

            if (pDataContract.ServiceRecordType == ServiceRecordTypeId.Wohnheimbuchung)
            {
                _EditAllowed = _DeleteAllowed = false;
            }
        }

        protected override ServiceRecordDC MapToDataContract(ServiceRecordDC pDataContract, bool doCommit)
        {
            return CopyToDataContract(pDataContract);
        }

        private ServiceRecordDC CopyToDataContract(ServiceRecordDC pDataContract)
        {
            var duration = 0;
            if (_Duration.HasValue)
            {
                duration = _Duration.Value;
            }

            var date = _Date.Value;
            var time = _StartTime.Value;

            pDataContract.Start = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second);

			if (BeWoApp.AppSettings.IsEndDateVisible)
			{
				if (_EndTime == null || _EndTime.Value.Date < pDataContract.Start.Value.Date)
				{
					_EndTime = pDataContract.Start;
				}

				if (_EndTime == null || pDataContract.Start.Value.Date == _EndTime.Value.Date)
				{
					pDataContract.End = pDataContract.Start.Value.AddMinutes(duration);
				}
				else
				{
					pDataContract.End = new DateTime(_EndTime.Value.Year, _EndTime.Value.Month, _EndTime.Value.Day, _EndTime.Value.Hour, _EndTime.Value.Minute, _EndTime.Value.Second);
				}
			}
			else
			{
				pDataContract.End = pDataContract.Start.Value.AddMinutes(duration);
			}
          
            pDataContract.Notice = _Notice;
            pDataContract.Notice2 = _Notice2;
            pDataContract.Notice3 = _Notice3;
            pDataContract.Notice4 = _Notice4;
            pDataContract.Notice5 = _Notice5;
            pDataContract.ServiceRecordType = _ServiceRecordType;
            pDataContract.DistanceInMeter = _DistanceInMeter;

            pDataContract.Employee = _Employee;
            pDataContract.Customer = _Customer;
            pDataContract.SupportConcept = _SupportConcept;
            pDataContract.CostBearer = _CostBearer;
            pDataContract.RoundedDuration = RoundedDuration;
            pDataContract.ServiceDescription = _ServiceDescription;
            pDataContract.Goals = GetSelectedGoals();

            pDataContract.GroupEmployeeCount = GroupEmployeeCount;
            pDataContract.GroupPersonCount = GroupPersonCount;
            pDataContract.GroupRoundedDuration = GroupRoundedDuration;
            pDataContract.GroupOid = GroupOid;

            return pDataContract;
        }

        private List<ValueListEntryDC> GetSelectedGoals()
        {
            var goals = new List<ValueListEntryDC>();

            AddCheckedGoals(GoalTree, goals);
            

            return goals;
        }

        private static void AddCheckedGoals(IEnumerable<SupportConceptGoalDC> goals, ICollection<ValueListEntryDC> selectedGoals)
        {
            foreach (var item in goals)
            {
                if (item.Children == null || item.Children.Count == 0)
                {
                    if (item.IsChecked)
                    {
                        selectedGoals.Add(item.GoalEntryDC);
                    }
                }
                else
                {
                    AddCheckedGoals(item.Children, selectedGoals);
                }
            }
        }

        private void TimeCheck()
        {
            var duration = 0;
            if (_Duration.HasValue)
            {
                duration = _Duration.Value;
            }

             StoreDirtyInformation(
                AreDifferent(DataContract.End, (_Date.Value + _StartTime.Value.TimeOfDay).AddMinutes(duration)) ||
                AreDifferent(DataContract.Start,_Date.Value + _StartTime.Value.TimeOfDay), "TIME");
        }

        #endregion
    }
}