#region <<< Using Directives >>>
using System;
#endregion

namespace Volpe.Cafe.EspressoUI.ModelCharts
{
    /// <summary>
    /// Provides an object to store compliance modeling statistics for a single data point of various data series to display in a model chart.
    /// </summary>
    [Serializable]
    struct ComplianceStatistics
    {

        #region <<< Methods >>>

        /// <summary>
        /// Returns all values containted within this statistics object as an array.
        /// The elements of the returned array are stored in the following order:
        ///     - CAFE metrics (Standard, CAFE, CAFE2Cycle, Shortfall),
        ///     - CO-2 metrics (CO2Standard, CO2Rating, CO2Shortfall),
        ///     - Compliance Costs metrics (Fines, Costs),
        ///     - Effects Costs metrics (FuelSavings, CO2Savings, FuelCosts, EmissionsDamage).
        /// </summary>
        /// <returns>All values containted within this statistics object.</returns>
        public double[] ToArray()
        {
            return this.ToArray(ComplianceMetrics.All);
        }
        /// <summary>
        /// Returns the values containted within this statistics object as an array, filtered by the specified compliance metrics.
        /// The elements of the returned array are stored in the following order:
        ///     - CAFE metrics (Standard, CAFE, CAFE2Cycle, Shortfall),
        ///     - CO-2 metrics (CO2Standard, CO2Rating, CO2Shortfall),
        ///     - Compliance Costs metrics (Fines, Costs),
        ///     - Effects Costs metrics (FuelSavings, CO2Savings, FuelCosts, EmissionsDamage).
        /// </summary>
        /// <param name="metrics">The compliance metrics to use when populating the return array.</param>
        /// <returns>The filtered values containted within this statistics object.</returns>
        public double[] ToArray(ComplianceMetrics metrics)
        {
            double[] values = new double[this.CountMetrics(metrics)];
            int index = 0;

            if (metrics.HasCAFEValues())
            {
                values[index++] = this.Standard;
                values[index++] = this.CAFE;
                values[index++] = this.CAFE2Cycle;
                values[index++] = this.Shortfall;
            }
            if (metrics.HasCO2Values())
            {
                values[index++] = this.CO2Standard;
                values[index++] = this.CO2Rating;
                values[index++] = this.CO2Shortfall;

            }
            if (metrics.HasComplianceCosts())
            {
                values[index++] = this.Fines;
                values[index++] = this.Costs;
            }
            if (metrics.HasEffectsCosts())
            {
                values[index++] = this.FuelSavings;
                values[index++] = this.CO2Savings;
                values[index++] = this.FuelCosts;
                values[index++] = this.EmissionsDamage;
            }

            return values;
        }

        int CountMetrics(ComplianceMetrics metrics)
        {
            int count = 0;
            //
            if (metrics.HasCAFEValues     ()) { count += CAFEValuesCount; }
            if (metrics.HasCO2Values      ()) { count += CO2ValuesCount; }
            if (metrics.HasComplianceCosts()) { count += ComplianceCostsCount; }
            if (metrics.HasEffectsCosts   ()) { count += EffectsCostsCount; }
            //
            return count;
        }

        #endregion

        #region <<< Properites >>>

        /// <summary>Gets or sets the total sales associated with the calculated statistics of this <see cref="ComplianceStatistics"/> instance.</summary>
        public double Sales { get; set; }

        /// <summary>Gets or sets the CAFE standard value to display in a model chart.</summary>
        public double Standard { get; set; }
        /// <summary>Gets or sets the CAFE rating value to display in a model chart.</summary>
        public double CAFE { get; set; }
        /// <summary>Gets or sets the 2-cycle CAFE rating value to display in a model chart.</summary>
        public double CAFE2Cycle { get; set; }
        /// <summary>Gets or sets the CAFE shortfall value to display in a model chart.</summary>
        public double Shortfall { get; set; }

        /// <summary>Gets or sets the CO-2 standard to value display in a model chart.</summary>
        public double CO2Standard { get; set; }
        /// <summary>Gets or sets the CO-2 rating to value display in a model chart.</summary>
        public double CO2Rating { get; set; }
        /// <summary>Gets or sets the CO-2 shortfall value to display in a model chart.</summary>
        public double CO2Shortfall { get; set; }

        /// <summary>Gets or sets the total CAFE fines, specified in millions of dollars, to display in a model chart.</summary>
        public double Fines { get; set; }
        /// <summary>Gets or sets the total technology costs, specified in millions of dollars, to display in a model chart.</summary>
        public double Costs { get; set; }

        /// <summary>Gets or sets the total fuel savings, specified in millions of dollars, to display in a model chart.</summary>
        public double FuelSavings { get; set; }
        /// <summary>Gets or sets the total CO-2 savings, specified in millions of dollars, to display in a model chart.</summary>
        public double CO2Savings { get; set; }
        /// <summary>Gets or sets the total fuel expenditures, specified in millions of dollars, to display in a model chart.</summary>
        public double FuelCosts { get; set; }
        /// <summary>Gets or sets the total cost of emissions damage, specified in millions of dollars, to display in a model chart.</summary>
        public double EmissionsDamage { get; set; }

        #endregion

        #region <<< Variables >>>

        const int CAFEValuesCount = 4;
        const int CO2ValuesCount = 3;
        const int ComplianceCostsCount = 2;
        const int EffectsCostsCount = 4;

        /// <summary>
        /// Represents an empty <see cref="ComplianceStatistics"/> object
        /// </summary>
        public static readonly ComplianceStatistics Empty = new ComplianceStatistics();

        #endregion

    }
}
