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

using BS.Shared.DataContracts;
using BS.Shared.Extensions;
using System.Linq;

namespace BeWo.ViewModel
{
    public class ServiceInvoicePeriodVM : AbstractDCMapperVM<ServiceInvoicePeriodDC>
    {
        public static string PropertyName_ApprovedAmount = "ApprovedAmount";

        public static string PropertyName_ApprovedAmountDefaultHourlyRate = "ApprovedAmountDefaultHourlyRate";

        public static string PropertyName_ApprovedBE = "ApprovedBE";

        public static string PropertyName_ApprovedFixedAmount = "ApprovedFixedAmount";

        public static string PropertyName_ApprovedHours = "ApprovedHours";

        public static string PropertyName_BEString = "BEString";

        public static string PropertyName_Claim = "Claim";

        public static string PropertyName_End = "End";

        public static string PropertyName_HoursNotBillableAbsence = "HoursNotBillableAbsence";

        public static string PropertyName_HoursNotBillableNotApproved = "HoursNotBillableNotApproved";

        public static string PropertyName_InvoiceItemList = "InvoiceItemList";

        public static string PropertyName_NotBillableString = "NotBillableString";

        public static string PropertyName_PeriodString = "PeriodString";

        public static string PropertyName_ServiceUnitName = "ServiceUnitName";

        public static string PropertyName_Start = "Start";

        public static string PropertyName_AccountingInterval = "AccountingInterval";

        private decimal? _ApprovedAmountDefaultHourlyRate;

        private decimal? _ApprovedBE;

        private decimal? _ApprovedFixedAmount;

        private decimal? _ApprovedHours;

        private decimal? _Claim;

        private DateTime? _End;

        private decimal _HoursNotBillableAbsence;

        private decimal _HoursNotBillableNotApproved;

        private InvoiceItemListVM _InvoiceItemList;

        private string _ServiceUnitName;

        private DateTime? _Start;

        private AccountingIntervalType? _AccountingInterval;

        public ServiceInvoicePeriodVM(ServiceInvoicePeriodDC pDC)
            : base(pDC, !pDC.ServiceInvoicePeriodOid.HasValue) {}

        public decimal? ApprovedAmount
        {
            get
            {
                return this._ApprovedAmountDefaultHourlyRate.HasValue
                           ? this._ApprovedAmountDefaultHourlyRate
                           : this._ApprovedFixedAmount;
            }
        }

        public decimal? ApprovedAmountDefaultHourlyRate
        {
            get
            {
                return this._ApprovedAmountDefaultHourlyRate;
            }

            set
            {
                if (this.AreDifferent(this._ApprovedAmountDefaultHourlyRate, value))
                {
                    this._ApprovedAmountDefaultHourlyRate = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ApprovedAmountDefaultHourlyRate, value), PropertyName_ApprovedAmountDefaultHourlyRate);
                    this.FirePropertyChanged(PropertyName_ApprovedAmountDefaultHourlyRate);
                }
            }
        }

        public decimal? ApprovedBE
        {
            get
            {
                return this._ApprovedBE;
            }

            set
            {
                if (this.AreDifferent(this._ApprovedBE, value))
                {
                    this._ApprovedBE = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ApprovedBE, value), PropertyName_ApprovedBE);
                    this.FirePropertyChanged(PropertyName_ApprovedBE);
                }
            }
        }

        public decimal? ApprovedFixedAmount
        {
            get
            {
                return this._ApprovedFixedAmount;
            }

            set
            {
                if (this.AreDifferent(this._ApprovedFixedAmount, value))
                {
                    this._ApprovedFixedAmount = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ApprovedFixedAmount, value), PropertyName_ApprovedFixedAmount);
                    this.FirePropertyChanged(PropertyName_ApprovedFixedAmount);
                }
            }
        }

        public decimal? ApprovedHours
        {
            get
            {
                if (this._ApprovedHours.HasValue)
                    return Math.Round(this._ApprovedHours.Value, 2, MidpointRounding.AwayFromZero);
                return null;
            }

            set
            {
                if (this.AreDifferent(this._ApprovedHours, value))
                {
                    this._ApprovedHours = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ApprovedHours, value), PropertyName_ApprovedHours);
                    this.FirePropertyChanged(PropertyName_ApprovedHours);
                }
            }
        }

        public string BEString
        {
            get
            {
                return String.Format("({0:0.00} {1})", this._ApprovedBE, this._ServiceUnitName);
            }
        }

        public decimal? Claim
        {
            get
            {
                return this._Claim;
            }

            set
            {
                if (this.AreDifferent(this._Claim, value))
                {
                    this._Claim = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.Claim, value), PropertyName_Claim);
                    this.FirePropertyChanged(PropertyName_Claim);
                }
            }
        }

        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 DateTime? End
        {
            get
            {
                return this._End;
            }

            set
            {
                if (this.AreDifferent(this._End, value))
                {
                    this._End = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.End, value), PropertyName_End);
                    this.FirePropertyChanged(PropertyName_End);
                    this.FirePropertyChanged(PropertyName_PeriodString);
                }
            }
        }

        public decimal HoursNotBillableAbsence
        {
            get
            {
                return this._HoursNotBillableAbsence;
            }

            set
            {
                if (this.AreDifferent(this._HoursNotBillableAbsence, value))
                {
                    this._HoursNotBillableAbsence = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.HoursNotBillableAbsence, value), PropertyName_HoursNotBillableAbsence);
                    this.FirePropertyChanged(PropertyName_HoursNotBillableAbsence);
                }
            }
        }

        public decimal HoursNotBillableNotApproved
        {
            get
            {
                return this._HoursNotBillableNotApproved;
            }

            set
            {
                if (this.AreDifferent(this._HoursNotBillableNotApproved, value))
                {
                    this._HoursNotBillableNotApproved = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.HoursNotBillableNotApproved, value), PropertyName_HoursNotBillableNotApproved);
                    this.FirePropertyChanged(PropertyName_HoursNotBillableNotApproved);
                }
            }
        }

        public InvoiceItemListVM InvoiceItemList
        {
            get
            {
                return this._InvoiceItemList;
            }

            set
            {
                if (this.AreDifferent(this._InvoiceItemList, value))
                {
                    this._InvoiceItemList = value;
                    this.FirePropertyChanged(PropertyName_InvoiceItemList);
                }
            }
        }

        public string NotBillableString
        {
            get
            {
                if (this._HoursNotBillableAbsence == 0 && this._HoursNotBillableNotApproved == 0)
                {
                    return string.Empty;
                }
                else
                {
                    var s = "Nicht abrechenbare geleistete Stunden im Zeitraum: ";
                    if (this._HoursNotBillableAbsence > 0)
                    {
                        s += string.Format("{0:0.00} (Klient abwesend) ", this._HoursNotBillableAbsence);
                        if (this._HoursNotBillableNotApproved > 0)
                        {
                            s += " + ";
                        }
                    }

                    if (this._HoursNotBillableNotApproved > 0)
                    {
                        s += string.Format("{0:0.00} (nicht bewilligt) ", this._HoursNotBillableNotApproved);
                    }

                    return s;
                }
            }
        }

        public string ShortDescription
        {
            get
            {
                String str = CustomerString;
                if (String.IsNullOrEmpty(str))
                    str = PeriodString;
                else
                {
                    if (this.DataContract.SupportConceptApprovalPeriod != null && this.DataContract.SupportConceptApprovalPeriod.ServiceCategory != null)
                    {
                        str += ", " + this.DataContract.SupportConceptApprovalPeriod.ServiceCategory.Name;
                    }
                }
                return str;
            }
        }

        public string PeriodString
        {
            get
            {
                String periodString = String.Empty;


                if (this.DataContract.SupportConceptApprovalPeriod != null && this.DataContract.SupportConceptApprovalPeriod.ServiceCategory != null)
                {
                    periodString = this.DataContract.SupportConceptApprovalPeriod.ServiceCategory.Name;
                }

                if (this._Start.HasValue && this._End.HasValue)
                {
                    if (periodString.Length > 0)
                        periodString += " ";
                    periodString += this._Start.Value.ToShortDateString() + " - " +
                       this._End.Value.ToShortDateString();
                }
                return periodString;

            }
        }

        public string CustomerString
        {
            get
            {
                
                if (this.DataContract.Customer != null)
                {
                    return this.DataContract.Customer.ToString();
                }
                return null;
            }
        }

        public string ServiceUnitName
        {
            get
            {
                return this._ServiceUnitName;
            }

            set
            {
                if (this.AreDifferent(this._ServiceUnitName, value))
                {
                    this._ServiceUnitName = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ServiceUnitName, value), PropertyName_ServiceUnitName);
                    this.FirePropertyChanged(PropertyName_ServiceUnitName);
                }
            }
        }

        public DateTime? Start
        {
            get
            {
                return this._Start;
            }

            set
            {
                if (this.AreDifferent(this._Start, value))
                {
                    this._Start = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.Start, value), PropertyName_Start);
                    this.FirePropertyChanged(PropertyName_Start);
                    this.FirePropertyChanged(PropertyName_PeriodString);
                }
            }
        }

        protected override void InitByDataContract(ServiceInvoicePeriodDC pDataContract)
        {
            this._ApprovedFixedAmount = pDataContract.ApprovedFixedAmount;
            this._ApprovedHours = pDataContract.ApprovedHours;
            this._End = pDataContract.End;
            this._InvoiceItemList = new InvoiceItemListVM(pDataContract.InvoiceItems);
            this._Start = pDataContract.Start;
            this._ApprovedBE = pDataContract.ApprovedBE;
            this._ServiceUnitName = pDataContract.ServiceUnitName;
            this._Claim = pDataContract.Claim;
            this._ApprovedAmountDefaultHourlyRate = pDataContract.ApprovedAmountDefaultHourlyRate;
            this._HoursNotBillableAbsence = pDataContract.HoursNotBillableAbsence;
            this._HoursNotBillableNotApproved = pDataContract.HoursNotBillableNotApproved;
            this._AccountingInterval = pDataContract.AccountingInterval;
        }

        protected override ServiceInvoicePeriodDC MapToDataContract(ServiceInvoicePeriodDC pDataContract, bool doCommit)
        {
            pDataContract.ApprovedFixedAmount = this._ApprovedFixedAmount;
            pDataContract.ApprovedHours = this._ApprovedHours;
            pDataContract.End = this._End;
            pDataContract.InvoiceItems = this._InvoiceItemList.CopyToDCList(true);
            pDataContract.Start = this._Start;
            pDataContract.ApprovedBE = this._ApprovedBE;
            pDataContract.ServiceUnitName = this._ServiceUnitName;
            pDataContract.Claim = this._Claim;
            pDataContract.ApprovedAmountDefaultHourlyRate = this._ApprovedAmountDefaultHourlyRate;
            pDataContract.HoursNotBillableAbsence = this._HoursNotBillableAbsence;
            pDataContract.HoursNotBillableNotApproved = this._HoursNotBillableNotApproved;
            pDataContract.AccountingInterval = this._AccountingInterval;

            return pDataContract;
        }
    }
}