using System;
using Volpe.Cafe.MarketData.Design;
using Volpe.Cafe.ModelSettings;

namespace Volpe.Cafe.Model
{
    /// <summary>
    /// Provides a default implementation of the <see cref="IModelingProgress"/> interface.
    /// </summary>
    [Serializable]
    public class ModelingProgress : IModelingProgress
    {

        #region <<< Constructors >>>

        /// <summary>
        /// Initializes a new instance of the <see cref="ModelingProgress"/> class using the specified parameters,
        /// optionally, including additional modeling progress information.
        /// </summary>
        /// <param name="scen">The scenario currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="iteration">The iteration currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="year">The model year currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="mfr">The manufacturer currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="additionalInfo">Additional modeling progress information. This value may be null.</param>
        public ModelingProgress(Scenario scen, int? iteration, ModelYear year, IManufacturer mfr, object additionalInfo = null)
            : this(null, scen, iteration, year, mfr, additionalInfo) { }
        /// <summary>
        /// Initializes a new instance of the <see cref="ModelingProgress"/> class using the specified progress string,
        /// optionally, including additional modeling progress information.
        /// </summary>
        /// <param name="progressString">The progress string to display in the UI. This value may be null.</param>
        /// <param name="additionalInfo">Additional modeling progress information. This value may be null.</param>
        public ModelingProgress(string progressString, object additionalInfo = null)
            : this(progressString, null, null, null, null, additionalInfo) { }
        /// <summary>
        /// Initializes a new instance of the <see cref="ModelingProgress"/> class using the specified parameters.
        /// </summary>
        /// <param name="progressString">The progress string to display in the UI. This value may be null.</param>
        /// <param name="scen">The scenario currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="iteration">The iteration currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="year">The model year currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="mfr">The manufacturer currently being analyzed by the modeling system. This value may be null.</param>
        /// <param name="additionalInfo">Additional modeling progress information. This value may be null.</param>
        protected ModelingProgress(string progressString, Scenario scen, int? iteration, ModelYear year, IManufacturer mfr,
            object additionalInfo)
        {
            this.ProgressString = progressString;
            this.Scenario       = scen;
            this.Iteration      = iteration;
            this.ModelYear      = year;
            this.Manufacturer   = mfr;
            this.AdditionalInfo = additionalInfo;
        }

        #endregion

        #region <<< Methods >>>

        /// <summary>
        /// Returns a string that represents the current <see cref="ModelingProgress"/> instance.
        /// </summary>
        /// <returns>A string that represents the current <see cref="ModelingProgress"/> instance.</returns>
        public override string ToString()
        {
            if (this.ProgressString != null)
            {
                return this.ProgressString;
            }
            else if (this.Scenario == null)
            {
                return "No progress information available.";
            }
            else
            {   // build the mfr progress string
                string mfrProgress = string.Empty;
                if (this.Manufacturer != null)
                {
                    var mfrRevision = this.Manufacturer.GetRevision(this.ModelYear?.Year);
                    var stats = mfrRevision.ComplianceStats;
                    var costs = mfrRevision.ComplianceCosts;
                    RCDouble techCost = new RCDouble();
                    for (int i = 0; i < techCost.Items.Length; i++) {
                        techCost.Items[i] = costs.Items[i].TechCost;
                    }

                    mfrProgress =
                        this.Manufacturer.ProperName +
                        "\n  CAFE Standard: " + stats.Standard   .ToString(2) +
                        "\n  CAFE Rating  : " + stats.CAFERating .ToString(2) +
                        "\n  CAFE Credits : " + stats.Credits    .ToString(0) +
                        "\n  CAFE Fines   : " + stats.Fines      .ToString(0) +
                        "\n  --------------------------------------------------" +
                        "\n  CO2 Standard : " + stats.CO2Standard.ToString(0) +
                        "\n  CO2 Rating   : " + stats.CO2Rating  .ToString(0) +
                        "\n  CO2 Credits  : " + stats.CO2Credits .ToString(0) +
                        "\n  --------------------------------------------------" +
                        "\n  Tech Costs   : " + techCost.ToString(0);
                }
                // add base progress and return
                return
                      "Scenario    : " + ((this.Scenario     == null) ? "N/A" : this.Scenario.ToString()) +
                    "\nIteration   : " + ((this.Iteration    == null) ? "N/A" : this.Iteration.ToString()) +
                    "\nModel Year  : " + ((this.ModelYear    == null) ? "N/A" : this.ModelYear.ToString()) +
                    "\nManufacturer: " + ((this.Manufacturer == null) ? "N/A" : mfrProgress);
            }
        }

        #endregion

        #region <<< Properties >>>

        /// <summary>Gets the progress string to display in the UI. This value may be null.</summary>
        public virtual string ProgressString { get; protected set; }

        /// <summary>Gets the scenario currently being analyzed by the modeling system. This value may be null.</summary>
        public virtual Scenario Scenario { get; protected set; }
        /// <summary>Gets the iteration currently being analyzed by the modeling system. This value may be null.</summary>
        public virtual int? Iteration { get; protected set; }
        /// <summary>Gets the model year currently being analyzed by the modeling system. This value may be null.</summary>
        public virtual ModelYear ModelYear { get; protected set; }
        /// <summary>Gets the manufacturer currently being analyzed by the modeling system. This value may be null.</summary>
        public virtual IManufacturer Manufacturer { get; protected set; }

        /// <summary>Gets or sets additional modeling progress information associated with this
        ///     <see cref="ModelingProgress"/> instance. This value may be null.</summary>
        public virtual object AdditionalInfo { get; set; }

        #endregion

    }
}
