using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using BS.Shared;
using BS.Shared.Core;
using BeWo.Validation;

using BS.Shared.DataContracts;
using BeWo.ViewModel.ListViewModel;

namespace BeWo.ViewModel
{
    public class ServiceCategoryVM : AbstractDCMapperVM<ServiceCategoryDC>
    {
        public static string PropertyName_Abbreviation = "Abbreviation";

        public static string PropertyName_IsBillable = "IsBillable";

        public static string PropertyName_OhneHilfeplan = "OhneHilfeplan";

        public static string PropertyName_IsDeleteable = "IsDeleteable";

        public static string PropertyName_Name = "Name";

        public static string PropertyName_Percentage = "Percentage";

        public static string PropertyName_Position = "Position";

        public static string PropertyName_BillableAmount = "BillableAmount";

        public static string PropertyName_AccountingInterval = "AccountingInterval";

        public static string PropertyName_ScopeType = "ScopeType";

        public static string PropertyName_CostRatePeriods = "CostRatePeriods";

        public static string PropertyName_CurrentAmount = "CurrentAmount";

		public static string PropertyName_IsDefault = "IsDefault";

        private string _Abbreviation;

        private bool _IsBillable;

        private AccountingvisibilityType? _OhneHilfeplan;

        private bool _IsDeleteable = true;

        private string _Name;

        private decimal _Percentage;

        private int _Position;

        private decimal _BillableAmount;

		private bool _IsDefault;

        private AccountingIntervalType? _AccountingInterval;

        private ScopeTypeId _ScopeType;

        private CostRatePeriodListVM _CostRatePeriods;
        
        public ServiceCategoryVM(ServiceCategoryDC pDataContract) : base(pDataContract, pDataContract.ServiceCategoryOid == null)
        {
        }

        public string Abbreviation
        {
            get { return this._Abbreviation; }

            set
            {
                if (this.AreDifferent(this._Abbreviation, value))
                {
                    this._Abbreviation = value;

                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.Abbreviation, value), PropertyName_Abbreviation);

                    this.FirePropertyChanged(PropertyName_Abbreviation);
                }
            }
        }

        public bool IsBillable
        {
            get { return this._IsBillable; }

            set
            {
                if (this.AreDifferent(this._IsBillable, value))
                {
                    this._IsBillable = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.IsBillable, value), PropertyName_IsBillable);
                    this.FirePropertyChanged(PropertyName_IsBillable);
                }
            }
        }

        public AccountingvisibilityType? OhneHilfeplan
        {
            get { return this._OhneHilfeplan; }

            set
            {
				if (this.AreDifferent(this._OhneHilfeplan, value))
                {
					this._OhneHilfeplan = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.OhneHilfeplan, value), PropertyName_OhneHilfeplan);
                    this.FirePropertyChanged(PropertyName_OhneHilfeplan);
                }
            }
        }

        public bool IsDeleteable
        {
            get { return this._IsDeleteable; }
        }

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

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

        public decimal Percentage
        {
            get { return this._Percentage; }

            set
            {
                if (this.AreDifferent(this._Percentage, value))
                {
                    this._Percentage = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.Percentage, value), PropertyName_Percentage);
                    this.FirePropertyChanged(PropertyName_Percentage);
                }
            }
        }

        public int Position
        {
            get { return this._Position; }

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

        public decimal BillableAmount
        {
            get { return this._BillableAmount; }

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

		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 AccountingIntervalType? AccountingInterval
        {
            get { return this._AccountingInterval; }

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


        public ScopeTypeId ScopeType
        {
            get { return this._ScopeType; }

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

        public CostRatePeriodListVM CostRatePeriods
        {
            get { return this._CostRatePeriods; }

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

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

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

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

        protected override void InitByDataContract(ServiceCategoryDC pDataContract)
        {
            if (!this.IsNew)
            {
                this._Name = pDataContract.Name;
                this._Abbreviation = pDataContract.Abbreviation;
                this._Percentage = pDataContract.Percentage;
                this._IsBillable = pDataContract.IsBillable;
                this._OhneHilfeplan = pDataContract.OhneHilfeplan;
                this._IsDeleteable = !pDataContract.IsSystemEntry;
                this._Position = pDataContract.Position;
                this._BillableAmount = pDataContract.BillableAmount;
                this._AccountingInterval = pDataContract.AccountingInterval;
                this._ScopeType = pDataContract.ScopeType;
	            this._IsDefault = pDataContract.IsDefault;
            }
            else
            {
                this._Percentage = 100m;
            }
			if (_OhneHilfeplan == null)
			{
				_OhneHilfeplan = AccountingvisibilityType.Beides;
			}

            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
                            });
                    }
                });

            this._CostRatePeriods = new CostRatePeriodListVM(pDataContract.CostRatePeriods);

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

        protected override ServiceCategoryDC MapToDataContract(ServiceCategoryDC pDataContract, bool doCommit)
        {
            pDataContract.Name = this._Name;
            pDataContract.Abbreviation = this._Abbreviation;
            pDataContract.IsBillable = this._IsBillable;
            pDataContract.OhneHilfeplan = this._OhneHilfeplan;
            pDataContract.Percentage = this._Percentage;
            pDataContract.Position = this._Position;
            pDataContract.BillableAmount = this._BillableAmount;
            pDataContract.AccountingInterval = this._AccountingInterval;
            pDataContract.ScopeType = this._ScopeType;
	        pDataContract.IsDefault = this._IsDefault;

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

            List<CostRatePeriodDC> crpList = this._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;
        }
    }
}