using System;

namespace Volpe.Cafe.EffectsData
{
    /// <summary>
    /// Provides modeling effects for upstream and tailpipe vehicle emissions.
    /// </summary>
    [Serializable]
    public sealed class EmissionEffects : IAppendable
    {
        /// <summary>
        /// Gets the upstream emissions (from all stages of fuel production and distribution).
        /// </summary>
        public EmissionsValue Upstream { get; } = new EmissionsValue();

        /// <summary>
        /// Gets the tailpipe emissions (from vehicle operation).
        /// </summary>
        public EmissionsValue Tailpipe { get; } = new EmissionsValue();

        /// <summary>
        /// Gets or sets the Particulate Matter (diameter of ~2.5 micrometers) emissions arising from brake and tire
        /// wear.
        /// </summary>
        public double BrakeTireWearPM { get; set; }

        /// <summary>
        /// Returns the total emissions (from all stages of fuel production and distribution, and from vehicle
        /// operation) for the specified pollutant.
        /// </summary>
        /// <param name="pollutant">The pollutant for which to obtain the total emissions.</param>
        public double GetTotalEmissions(Pollutant pollutant)
        {
            double totalEmissions = this.Upstream[pollutant] + this.Tailpipe[pollutant];

            if (pollutant == Pollutant.PM) {
                totalEmissions += this.BrakeTireWearPM;
            }

            return totalEmissions;
        }

        /// <summary>
        /// Resets all emission effects values to zero.
        /// </summary>
        public void Clear()
        {
            this.Upstream.Clear();
            this.Tailpipe.Clear();
            this.BrakeTireWearPM = 0;
        }

        /// <summary>
        /// Appends all values from the specified <see cref="EmissionEffects"/> object to this instance.
        /// </summary>
        public void Append(EmissionEffects value)
        {
            foreach (Pollutant pollutant in Pollutants.List) {
                this.Upstream[pollutant] += value.Upstream[pollutant];
                this.Tailpipe[pollutant] += value.Tailpipe[pollutant];
            }

            this.BrakeTireWearPM += value.BrakeTireWearPM;
        }

        //----- explicit interface implementation -----
        void IAppendable.Append(IAppendable value)
        {
            this.Append((EmissionEffects)value);
        }

    }
}
