using System;

namespace Volpe.Cafe
{
    /// <summary>
    /// Represents an object that stores modeling data, as double precision numeric values, for each petroleum
    /// production category.
    /// </summary>
    [Serializable]
    public class PetroleumCategoryValue : ICloneable
    {
        #region <<< Constructors >>>

        /// <summary>
        /// Initializes a new instance of the <see cref="PetroleumCategoryValue"/> class using the specified values.
        /// </summary>
        public PetroleumCategoryValue(
            double extraction, double transportation, double refining, double fuelTSD, double total)
        {
            this.Extraction = extraction;
            this.Transportation = transportation;
            this.Refining = refining;
            this.FuelTSD = fuelTSD;
            this.Total = total;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PetroleumCategoryValue"/> class using the specified initial
        /// value for all members.
        /// </summary>
        internal PetroleumCategoryValue(double initialValue)
            : this(initialValue, initialValue, initialValue, initialValue, initialValue) { }

        #endregion

        #region <<< Properties >>>

        //----- static values -----
        /// <summary>Gets the <see cref="PetroleumCategoryValue"/> whose elements are all 0.</summary>
        public static PetroleumCategoryValue Zero => new PetroleumCategoryValue(0D);
        /// <summary>Gets the <see cref="PetroleumCategoryValue"/> whose elements are all 1.</summary>
        public static PetroleumCategoryValue One => new PetroleumCategoryValue(1D);

        //----- instance values -----
        /// <summary>Gets or sets a value from a petroleum extraction category.</summary>
        public double Extraction { get; set; }
        /// <summary>Gets or sets a value from a petroleum transportation category.</summary>
        public double Transportation { get; set; }
        /// <summary>Gets or sets a value from a petroleum refining category.</summary>
        public double Refining { get; set; }
        /// <summary>Gets or sets a value from a fuel transportation, storage, and distribution category.</summary>
        public double FuelTSD { get; set; }

        /// <summary>Gets or sets an aggregate value from all categories.</summary>
        public double Total { get; set; }

        #endregion

        #region <<< Methods >>>

        #region < ICloneable Members >

        /// <summary>
        /// Creates a new object that is a copy of the current <see cref="PetroleumCategoryValue"/> instance.
        /// </summary>
        /// <returns>A new object that is a copy of this <see cref="PetroleumCategoryValue"/>.</returns>
        object ICloneable.Clone()
        {
            return this.Clone();
        }
        /// <summary>
        /// Creates a copy of the current <see cref="PetroleumCategoryValue"/> instance.
        /// </summary>
        /// <returns>A new object that is a copy of this <see cref="PetroleumCategoryValue"/>.</returns>
        public PetroleumCategoryValue Clone()
        {
            return new PetroleumCategoryValue(
                this.Extraction, this.Transportation, this.Refining, this.FuelTSD, this.Total);
        }

        #endregion

        /// <summary>
        /// Returns the string representation of this <see cref="PetroleumCategoryValue"/> instance.
        /// </summary>
        /// <returns>The string representation of the <see cref="PetroleumCategoryValue"/> instance.</returns>
        public override string ToString()
        {
            return "{Extraction=" + this.Extraction.ToString()
                + ", Transportation=" + this.Transportation.ToString()
                + ", Refining=" + this.Refining.ToString()
                + ", FuelTSD=" + this.FuelTSD.ToString()
                + ", Total=" + this.Total.ToString() + "}";
        }

        /// <summary>
        /// Resets all members of this instance to their default values (0).
        /// </summary>
        public void Clear()
        {
            this.Extraction = 0;
            this.Transportation = 0;
            this.Refining = 0;
            this.FuelTSD = 0;
            this.Total = 0;
        }

        #endregion
    }
}
