using System;

namespace Volpe.Cafe.MarketData
{
    /// <summary>
    /// Defines the compliance costs associated with application of fuel improving technologies, as well as costs
    /// associated with credits and adjustments from off-cycle technologies.
    /// </summary>
    [Serializable]
    public class ComplianceCosts : ICloneable, IAppendable
    {
        /// <summary>
        /// Gets or sets the costs associated with improvements in air conditioning efficiency that a manufacturer has
        /// claimed toward compliance with either NHTSA's CAFE standards or EPA's CO-2 standards.
        /// </summary>
        public double ACEfficiencyCost { get; set; }
        /// <summary>
        /// Gets or sets the costs associated with improvements in air conditioning leakage that a manufacturer has
        /// claimed toward compliance with EPA's CO-2 standards.
        /// </summary>
        public double ACLeakageCost { get; set; }
        /// <summary>
        /// Gets or sets the costs associated with off-cycle credits that a manufacturer has claimed toward compliance
        /// with either NHTSA's CAFE standards or EPA's CO-2 standards.
        /// </summary>
        public double OffCycleCost { get; set; }

        /// <summary>
        /// Gets or sets the battery-related technology costs associated with application of fuel improving 
        /// technologies.
        /// </summary>
        public double BatteryTechCost { get; set; }
        /// <summary>
        /// Gets or sets the non-battery related technology costs associated with application of fuel improving 
        /// technologies.
        /// </summary>
        public double NonBatteryTechCost { get; set; }
        /// <summary>
        /// Gets the subtotal of battery and non-battery technology costs associated with application of fuel improving 
        /// technologies.
        /// </summary>
        public double TechCost => this.BatteryTechCost + this.NonBatteryTechCost;

        /// <summary>
        /// Gets or sets the regulatory costs attributed to a combination of fuel improving technology application and
        /// civil penalties paid by a manufacturer for non-compliance.
        /// </summary>
        public double RegCost { get; set; }

        /// <summary>
        /// Gets or sets the technology maintenance and repair costs associated with application of fuel improving
        /// technologies.
        /// </summary>
        public double MaintRepairCost { get; set; }

        /// <summary>
        /// Gets the total costs associated with AC efficiency, AC leakage, and off-cycle credits that a manufacturer
        /// has claimed toward compliance with either NHTSA's CAFE standards or EPA's CO-2 standards.
        /// </summary>
        public double TotalAcOcCost => this.ACEfficiencyCost + this.ACLeakageCost + this.OffCycleCost;
        /// <summary>
        /// Gets the total of technology costs associated with application of fuel improving technologies, as well as
        /// the costs associated with AC efficiency, AC leakage, and off-cycle credits that a manufacturer has claimed
        /// toward compliance with either NHTSA's CAFE standards or EPA's CO-2 standards.
        /// </summary>
        public double TotalTechCost => this.TechCost + this.TotalAcOcCost;

        /// <summary>
        /// Resets all compliance costs to zero.
        /// </summary>
        public void Clear()
        {
            this.ACEfficiencyCost = 0;
            this.ACLeakageCost = 0;
            this.OffCycleCost = 0;
            this.BatteryTechCost = 0;
            this.NonBatteryTechCost = 0;
            this.RegCost = 0;
            this.MaintRepairCost = 0;
        }

        /// <summary>
        /// Appends all values from the specified <see cref="ComplianceCosts"/> object to this instance.
        /// </summary>
        public void Append(ComplianceCosts value)
        {
            this.ACEfficiencyCost += value.ACEfficiencyCost;
            this.ACLeakageCost += value.ACLeakageCost;
            this.OffCycleCost += value.OffCycleCost;
            this.BatteryTechCost += value.BatteryTechCost;
            this.NonBatteryTechCost += value.NonBatteryTechCost;
            this.RegCost += value.RegCost;
            this.MaintRepairCost += value.MaintRepairCost;
        }

        /// <summary>
        /// Creates a new object that is a copy of the current <see cref="ComplianceCosts"/> instance.
        /// </summary>
        /// <returns>A new object that is a copy of this <see cref="ComplianceCosts"/>.</returns>
        public ComplianceCosts Clone()
        {
            return new ComplianceCosts {
                ACEfficiencyCost = this.ACEfficiencyCost,
                ACLeakageCost = this.ACLeakageCost,
                OffCycleCost = this.OffCycleCost,
                BatteryTechCost = this.BatteryTechCost,
                NonBatteryTechCost = this.NonBatteryTechCost,
                RegCost = this.RegCost,
                MaintRepairCost = this.MaintRepairCost
            };
        }

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

    }
}
