using System;
using System.Collections.Generic;

using Volpe.Cafe.Generic;
using Volpe.Cafe.MarketData.BaselineInfo;

namespace Volpe.Cafe.MarketData.Design
{
    /// <summary>
    /// Defines any vehicle component, produced by an original equipment manufacturer (OEM), that encapsulates a
    /// description of its engineering characteristics as well as provides an annual historic view of its revisions.
    /// </summary>
    /// <remarks>
    /// OEM components provide extensions to the <see cref="IOEMProduct"/>s, allowing for multiple vehicles to be
    /// aggregated, or "grouped", for technology application. Components include vehicle platforms, engines, and
    /// transmissions, and may be used directly by a vehicle.
    /// </remarks>
    /// <seealso cref="IOEMComponentInfo"/>
    /// <seealso cref="IOEMComponentRevision"/>
    public interface IOEMComponent : IOEMProduct, IOEMComponentInfo
    {
        /// <summary>
        /// Gets a description of baseline engineering characteristics for the <see cref="IOEMComponent"/>.
        /// </summary>
        new BaselineComponent BaselineInfo { get; }

        /// <summary>
        /// Gets the product information for the latest revision of the component, or the component's baseline
        /// engineering characteristics if no new revisions have been created yet.
        /// </summary>
        new IOEMComponentRevision RevisionInfo { get; }

        /// <summary>
        /// Gets an annual stream of <see cref="IOEMComponentRevision"/> objects, containing the revisions of
        /// component's engineering characteristics and compliance attributes.
        /// </summary>
        new IAnnualValue<IOEMComponentRevision> Revisions { get; }

        /// <summary>
        /// Gets a <see cref="IOEMComponentFamily"/> that this component belongs to.
        /// </summary>
        IOEMComponentFamily Family { get; }

        /// <summary>
        /// Gets a list of vehicles that use this component.
        /// </summary>
        IReadOnlyList<IVehicle> Vehicles { get; }

        /// <summary>
        /// Advances the revision year for the component by one, and creates a new component revision for that year.
        /// </summary>
        /// <returns>
        /// A <see cref="IOEMComponentRevision"/> object containing revision information for the new revision year.
        /// </returns>
        /// <remarks>
        /// This method must be called by the compliance model at the start of each new model year. That is, a
        /// component revision must be created for a given model year, before analysis of that year can begin.
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        ///     The component must be initialized for analysis before component revisions may be created.
        ///     -or-
        ///     A component revision may not be created for a model year beyond the last analysis year.
        /// </exception>
        new IOEMComponentRevision CreateRevision();

        /// <summary>
        /// Obtains a component revision for the specified model year.
        /// </summary>
        /// <param name="year">
        ///     The model year for which to obtain a component revision; or, specify null to return the component's
        ///     latest revision.
        /// </param>
        /// <returns>
        /// A component revision for the specified model year, or null, if the component does not have any revisions.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     The specified year is out-of-bounds of the minimum and maximum range of model years available for
        ///     analysis.
        /// </exception>
        new IOEMComponentRevision GetRevision(int? year = null);

        /// <summary>
        /// Condenses the revisions to only include the model years where component changes occurred. This method
        /// should typically be called at the end of analysis for a scenario or an iteration.
        /// </summary>
        void CondenseRevisions();

        /// <summary>
        /// Removes the specified <paramref name="vehicle"/> from this component.
        /// </summary>
        /// <param name="vehicle">The vehicle to remove.</param>
        /// <param name="analysisYear">
        ///     The model year that was being analyzed when the remove action was triggered.
        /// </param>
        /// <param name="applicationYear">
        ///     The initial model year during which a technology that triggered the remove action was installed on a
        ///     vehicle.
        /// </param>
        void RemoveVehicle(IVehicle vehicle, int analysisYear, int applicationYear);

    }
}
