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

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;

using BeWo.Validation;
using BeWo.ViewModel.ListViewModel;

namespace BeWo.ViewModel
{
	public class ServiceDescriptionVM : AbstractDCMapperVM<ServiceDescriptionDC>
	{
		public static string PropertyName_CategoryName = "CategoryName";

		public static string PropertyName_IsDeleteable = "IsDeleteable";

		public static string PropertyName_Name = "Name";

		public static string PropertyName_ServiceCategory = "ServiceCategory";

		public static string PropertyName_Position = "Position";

		public static string PropertyName_BillableAmount = "BillableAmount";

		public static string PropertyName_AccountingInterval = "AccountingInterval";

		public static string PropertyName_Unit = "Unit";

		public static string PropertyName_ScopeType = "ScopeType";

		public static string PropertyName_CostRatePeriods = "CostRatePeriods";

		public static string PropertyName_CurrentAmount = "CurrentAmount";

		public static string PropertyName_IsDefault = "IsDefault";

		public static string PropertyName_DoNotCheckOverlapping = "DoNotCheckOverlapping";

		private string _CategoryName;

		private bool _IsDeleteable = true;

		private string _Name;

		private int _Position;

		private decimal _BillableAmount;

		private bool _IsDefault;

		private bool _DoNotCheckOverlapping;

		private ServiceUnit _Unit;

		private AccountingIntervalType? _AccountingInterval;

		private ServiceCategoryDC _ServiceCategory;

		private ScopeTypeId _ScopeType;

		private CostRatePeriodListVM _CostRatePeriods;

		public ServiceDescriptionVM(ServiceDescriptionDC pDataContract)
			: base(pDataContract, pDataContract.ServiceDescriptionOid == null)
		{
		}

		public string CategoryName
		{
			get { return _CategoryName; }

			set
			{
				if (AreDifferent(_CategoryName, value))
				{
					_CategoryName = value;
					StoreDirtyInformation(AreDifferent(DataContract.CategoryName, value), PropertyName_CategoryName);
					FirePropertyChanged(PropertyName_CategoryName);
				}
			}
		}

		public bool IsDeleteable
		{
			get { return _IsDeleteable; }
		}

		[Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
		public string Name
		{
			get { return _Name; }

			set
			{
				if (AreDifferent(_Name, value))
				{
					_Name = value;
					StoreDirtyInformation(AreDifferent(DataContract.Name, value), PropertyName_Name);
					FirePropertyChanged(PropertyName_Name);
				}
			}
		}

		[Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
		public ServiceCategoryDC ServiceCategory
		{
			get { return _ServiceCategory; }

			set
			{
				if (AreDifferent(_ServiceCategory, value))
				{
					_ServiceCategory = value;
					CategoryName = value != null ? value.Name : string.Empty;
					FirePropertyChanged(PropertyName_ServiceCategory);
				}
			}
		}

		public int Position
		{
			get { return _Position; }

			set
			{
				if (AreDifferent(_Position, value))
				{
					_Position = value;
					StoreDirtyInformation(AreDifferent(DataContract.Position, value), PropertyName_Position);
					FirePropertyChanged(PropertyName_Position);
				}
			}
		}

		public decimal BillableAmount
		{
			get { return _BillableAmount; }

			set
			{
				if (AreDifferent(_BillableAmount, value))
				{
					_BillableAmount = value;
					StoreDirtyInformation(AreDifferent(DataContract.BillableAmount, value), PropertyName_BillableAmount);
					FirePropertyChanged(PropertyName_BillableAmount);
				}
			}
		}

		public AccountingIntervalType? AccountingInterval
		{
			get { return _AccountingInterval; }

			set
			{
				if (AreDifferent(_AccountingInterval, value))
				{
					_AccountingInterval = value;
					StoreDirtyInformation(AreDifferent(DataContract.AccountingInterval, value), PropertyName_AccountingInterval);
					FirePropertyChanged(PropertyName_AccountingInterval);
				}
			}
		}



		public ServiceUnit Unit
		{
			get { return _Unit; }

			set
			{
				if (AreDifferent(_Unit, value))
				{
					_Unit = value;
					StoreDirtyInformation(AreDifferent(DataContract.Unit, value), PropertyName_Unit);
					FirePropertyChanged(PropertyName_Unit);
				}
			}
		}

		public ScopeTypeId ScopeType
		{
			get { return _ScopeType; }

			set
			{
				if (AreDifferent(_ScopeType, value))
				{
					_ScopeType = value;
					StoreDirtyInformation(AreDifferent(DataContract.ScopeType, value), PropertyName_ScopeType);
					FirePropertyChanged(PropertyName_ScopeType);
				}
			}
		}

		public CostRatePeriodListVM CostRatePeriods
		{
			get { return _CostRatePeriods; }

			set
			{
				if (AreDifferent(_CostRatePeriods, value))
				{
					_CostRatePeriods = value;
					if (!_AccountingInterval.HasValue && _CostRatePeriods != null && _CostRatePeriods.VMList.Count > 0)
						AccountingInterval = AccountingIntervalType.Hourly;
					FirePropertyChanged(PropertyName_CostRatePeriods);
				}
			}
		}

		public bool IsDefault
		{
			get { return this._IsDefault; }

			set
			{
				if (this.AreDifferent(this._IsDefault, value))
				{
					this._IsDefault = value;
					this.StoreDirtyInformation(this.AreDifferent(this.DataContract.IsDefault, value), PropertyName_IsDefault);
					this.FirePropertyChanged(PropertyName_IsDefault);
				}
			}
		}

		public bool DoNotCheckOverlapping
		{
			get { return this._DoNotCheckOverlapping; }

			set
			{
				if (this.AreDifferent(this._DoNotCheckOverlapping, value))
				{
					this._DoNotCheckOverlapping = value;
					this.StoreDirtyInformation(this.AreDifferent(this.DataContract.IsDefault, value), PropertyName_DoNotCheckOverlapping);
					this.FirePropertyChanged(PropertyName_DoNotCheckOverlapping);
				}
			}
		}

		public CostRatePeriodVM CurrentAmount
		{
			get { return CostRatePeriods.GetCurrentlyValidRate(CostRatePeriodType.AmountOfMoney); }
		}

		public override bool IsDirty
		{
			get
			{
				if (_CostRatePeriods == null)
				{
					return false;
				}

				return base.IsDirty || _CostRatePeriods.IsDirty;
			}
		}

		protected override void InitByDataContract(ServiceDescriptionDC pDataContract)
		{
			if (!IsNew)
			{
				_Name = pDataContract.Name;
				_CategoryName = pDataContract.CategoryName;
				_ServiceCategory = pDataContract.Category;
				_IsDeleteable = !pDataContract.IsSystemEntry;
				_Position = pDataContract.Position;
				_BillableAmount = pDataContract.BillableAmount;
				_AccountingInterval = pDataContract.AccountingInterval;
				_Unit = pDataContract.Unit;
				_ScopeType = pDataContract.ScopeType;
				_IsDefault = pDataContract.IsDefault;
				_DoNotCheckOverlapping = pDataContract.DoNotCheckOverlapping;
			}

			if (pDataContract.CostRatePeriods == null)
			{
				pDataContract.CostRatePeriods = new List<CostRatePeriodDC>();
			}

			Utils.GetAllEnumValues<CostRatePeriodType>().ToList().ForEach(
				t =>
				{
					if (t == CostRatePeriodType.AmountOfMoney && !pDataContract.CostRatePeriods.Exists(i => i.CostRateType == t))
					{
						pDataContract.CostRatePeriods.Add(
							new CostRatePeriodDC
							{
								CostRateType = t
							});
					}
				});

			_CostRatePeriods = new CostRatePeriodListVM(pDataContract.CostRatePeriods);

			_CostRatePeriods.VMList.ListChanged += (s, e) =>
			{
				if (e.ListChangedType != ListChangedType.ItemChanged)
				{
					FirePropertyChanged(PropertyName_CostRatePeriods);

				}
				FirePropertyChanged(PropertyName_CurrentAmount);
			};
		}

		protected override ServiceDescriptionDC MapToDataContract(ServiceDescriptionDC pDataContract, bool doCommit)
		{
			pDataContract.Name = _Name;
			pDataContract.ScopeType = _ScopeType;
			pDataContract.IsDefault = _IsDefault;

			if (_ServiceCategory != null)
			{
				pDataContract.CategoryName = _ServiceCategory.Name;
				pDataContract.Category = _ServiceCategory;
				pDataContract.Position = _Position;
				pDataContract.BillableAmount = _BillableAmount;
				pDataContract.AccountingInterval = _AccountingInterval;
				pDataContract.Unit = _Unit;
				pDataContract.DoNotCheckOverlapping = _DoNotCheckOverlapping;
			}

			pDataContract.CostRatePeriods = new List<CostRatePeriodDC>();

			List<CostRatePeriodDC> crpList = _CostRatePeriods.CopyToDCList(doCommit);
			foreach (var costRatePeriodDc in crpList)
			{
				if (costRatePeriodDc.CostRateValue.HasValue && costRatePeriodDc.CostRateValue.Value > 0)
					pDataContract.CostRatePeriods.Add(costRatePeriodDc);
			}

			if (pDataContract.CostRatePeriods.Count == 0)
				pDataContract.AccountingInterval = null;


			return pDataContract;
		}
	}
}