using System;

namespace Volpe.Cafe.EffectsData
{
    /// <summary>
    /// Represents an object that stores modeling data based on various estimates.
    /// </summary>
    [Serializable]
    public class ValueByEstimate : IAppendable
    {
        /// <summary>
        /// Gets or sets the modeling data value associated with the <see cref="Estimates.Low"/> estimates.
        /// </summary>
        public double Low { get; set; }
        /// <summary>
        /// Gets or sets the modeling data value associated with the <see cref="Estimates.Average"/> estimates.
        /// </summary>
        public double Average { get; set; }
        /// <summary>
        /// Gets or sets the modeling data value associated with the <see cref="Estimates.High"/> estimates.
        /// </summary>
        public double High { get; set; }
        /// <summary>
        /// Gets or sets the modeling data value associated with the <see cref="Estimates.VeryHigh"/> estimates.
        /// </summary>
        public double VeryHigh { get; set; }

        /// <summary>
        /// Gets the modeling data value based on the given <see cref="Estimates"/>.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     The estimates specified does not represent a valid <see cref="Estimates"/>.
        /// </exception>
        public double this[Estimates estimates]
        {
            get {
                switch (estimates) {
                    case Estimates.Low: return this.Low;
                    case Estimates.Average: return this.Average;
                    case Estimates.High: return this.High;
                    case Estimates.VeryHigh: return this.VeryHigh;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(estimates));
                }
            }
            set {
                switch (estimates) {
                    case Estimates.Low:
                        this.Low = value;
                        break;

                    case Estimates.Average:
                        this.Average = value;
                        break;

                    case Estimates.High:
                        this.High = value;
                        break;

                    case Estimates.VeryHigh:
                        this.VeryHigh = value;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(estimates));
                }
            }
        }

        /// <summary>
        /// Resets all values to zero.
        /// </summary>
        public void Clear()
        {
            this.Low = 0;
            this.Average = 0;
            this.High = 0;
            this.VeryHigh = 0;
        }

        /// <summary>
        /// Appends all values from the specified <see cref="ValueByEstimate"/> object to this instance.<br/>
        /// </summary>
        public void Append(ValueByEstimate value)
        {
            this.Low += value.Low;
            this.Average += value.Average;
            this.High += value.High;
            this.VeryHigh += value.VeryHigh;
        }

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

    }
}
