using System;

namespace Volpe.Cafe.MarketData
{
    /// <summary>
    /// Defines the ownership costs associated with the purchase of a new vehicle.
    /// </summary>
    [Serializable]
    public class OwnershipCosts : ICloneable, IAppendable
    {
        /// <summary>
        /// Gets or sets the amount a buyer is expected to pay in taxes and fees for purchasing a new vehicle.
        /// </summary>
        public double TaxesAndFees { get; set; }
        /// <summary>
        /// Gets or sets the amount a buyer is expected to pay for financing a new vehicle purchase.
        /// </summary>
        public double FinancingCosts { get; set; }
        /// <summary>
        /// Gets or sets the amount a buyer is expected to pay for insuring a vehicle over its lifetime.
        /// </summary>
        public double InsuranceCosts { get; set; }

        /// <summary>
        /// Gets the sum of all ownership costs (taxes and fees, financing, and insurance costs).
        /// </summary>
        public double Total => this.TaxesAndFees + this.InsuranceCosts + this.FinancingCosts;

        /// <summary>
        /// Returns the string representation of this <see cref="OwnershipCosts"/> instance.
        /// </summary>
        /// <returns>The string representation of the <see cref="OwnershipCosts"/> instance.</returns>
        public override string ToString()
        {
            return $"{{TaxesAndFees={this.TaxesAndFees}, FinancingCosts={this.FinancingCosts}, " +
                   $"InsuranceCosts={this.InsuranceCosts}, Total={this.Total}}}";
        }

        /// <summary>
        /// Resets all ownership costs to zero.
        /// </summary>
        public void Clear()
        {
            this.TaxesAndFees = 0;
            this.FinancingCosts = 0;
            this.InsuranceCosts = 0;
        }

        /// <summary>
        /// Appends all values from the specified <see cref="OwnershipCosts"/> object to this instance.
        /// </summary>
        public void Append(OwnershipCosts value)
        {
            this.TaxesAndFees += value.TaxesAndFees;
            this.FinancingCosts += value.FinancingCosts;
            this.InsuranceCosts += value.InsuranceCosts;
        }

        /// <summary>
        /// Creates a new object that is a copy of the current <see cref="OwnershipCosts"/> instance.
        /// </summary>
        /// <returns>A new object that is a copy of this <see cref="OwnershipCosts"/>.</returns>
        public OwnershipCosts Clone()
        {
            return new OwnershipCosts
            {
                TaxesAndFees = this.TaxesAndFees,
                FinancingCosts = this.FinancingCosts,
                InsuranceCosts = this.InsuranceCosts
            };
        }

        //----- explicit interface implementation -----
        void IAppendable.Append(IAppendable value)
        {
            this.Append((OwnershipCosts)value);
        }
        object ICloneable.Clone()
        {
            return this.Clone();
        }

    }
}
