using System;
using Volpe.Cafe.EffectsData.Collections;

namespace Volpe.Cafe.EffectsData
{
    /// <summary>
    /// Provides an object to store various modeling effects and costs.
    /// </summary>
    [Serializable]
    public sealed class ModelingEffectsItem
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ModelingEffectsItem"/> class.
        /// </summary>
        /// <param name="socialDR">The discount rates at which the owner and societal costs are discounted.</param>
        /// <param name="consumerDR">The discount rates at which the consumer costs are discounted.</param>
        /// <param name="isAnnual">
        ///     <c>true</c>, if the <see cref="ModelingEffectsItem"/> is being initialized for annual effects;
        ///     <c>false</c>, if it is being initialized for aggregate effects.
        /// </param>
        public ModelingEffectsItem(double[] socialDR, double[] consumerDR, bool isAnnual)
        {
            this.GeneralEffects = (isAnnual) ? null : new GeneralEffectsCollection();
            this.EnergyEffects = new EnergyEffectsCollection();
            this.EmissionEffects = new EmissionEffectsCollection();
            this.SafetyEffects = new SafetyEffectsCollection();

            if (socialDR != null) {
                this.SocialCosts = new SocietalCostsCollection(0);
                this.DiscSocialCosts = Array.ConvertAll(socialDR, dr => new SocietalCostsCollection(dr));
            }

            if (consumerDR != null) {
                this.ConsumerCosts = new ConsumerCostsCollection(0);
                this.DiscConsumerCosts = Array.ConvertAll(consumerDR, dr => new ConsumerCostsCollection(dr));
            }
        }

        /// <summary>
        /// Gets the modeling effects related to various general vehicle attributes, which are not differentiated by
        /// vehicle age.
        /// </summary>
        public GeneralEffectsCollection GeneralEffects { get; private set; }

        /// <summary>
        /// Gets the modeling effects for energy consumption from vehicle operation.
        /// </summary>
        public EnergyEffectsCollection EnergyEffects { get; private set; }

        /// <summary>
        /// Gets the modeling effects for upstream and tailpipe vehicle emissions.
        /// </summary>
        public EmissionEffectsCollection EmissionEffects { get; private set; }

        /// <summary>
        /// Gets the modeling effects related to safety and adverse health impacts associated with vehicle operation.
        /// </summary>
        public SafetyEffectsCollection SafetyEffects { get; private set; }

        /// <summary>
        /// Gets the undiscounted owner and societal costs arising from the various modeling effects.
        /// </summary>
        public SocietalCostsCollection SocialCosts { get; private set; }

        /// <summary>
        /// Gets the discounted owner and societal costs arising from the various modeling effects. Each element of the
        /// array corresponds to a specific discount rate value. This value may be <c>null</c> if discounting has not
        /// been performed.
        /// </summary>
        public SocietalCostsCollection[] DiscSocialCosts { get; private set; }

        /// <summary>
        /// Gets the undiscounted consumer costs arising from the various modeling effects.
        /// </summary>
        public ConsumerCostsCollection ConsumerCosts { get; private set; }

        /// <summary>
        /// Gets the discounted consumer costs arising from the various modeling effects. Each element of the array
        /// corresponds to a specific discount rate value. This value may be <c>null</c> if discounting has not been
        /// performed.
        /// </summary>
        public ConsumerCostsCollection[] DiscConsumerCosts { get; private set; }

        /// <summary>
        /// Appends all modeling effects values from the specified <paramref name="value"/> to this instance.
        /// </summary>
        public void Append(ModelingEffectsItem value)
        {
            this.EnergyEffects.Append(value.EnergyEffects);
            this.EmissionEffects.Append(value.EmissionEffects);
            this.SafetyEffects.Append(value.SafetyEffects);

            if (this.SocialCosts != null) {
                this.SocialCosts.Append(value.SocialCosts);
                for (int j = 0; j < this.DiscSocialCosts.Length; j++) {
                    this.DiscSocialCosts[j].Append(value.DiscSocialCosts[j]);
                }
            }

            if (this.ConsumerCosts != null) {
                this.ConsumerCosts.Append(value.ConsumerCosts);
                for (int j = 0; j < this.DiscConsumerCosts.Length; j++) {
                    this.DiscConsumerCosts[j].Append(value.DiscConsumerCosts[j]);
                }
            }
        }

    }
}
