using System;

using Volpe.Cafe.EffectsData;
using Volpe.Cafe.Generic;
using Volpe.Cafe.Logging;
using Volpe.Cafe.MarketData.Design;
using Volpe.Cafe.ModelSettings;
using Volpe.Cafe.Reporting;
using Volpe.Cafe.UI;

namespace Volpe.Cafe.Model
{
    /// <summary>
    /// Provides an outline for implementing compliance models.
    /// </summary>
    [ModelDescription("ICompliance", "Provides an outline for implementing compliance models.", 1.3F)]
    public interface ICompliance
    {
        #region <<< Events >>>

        /// <summary>
        /// Occurs whenever the compliance model generates a prompt, which requires user action.
        /// </summary>
        event PromptEventHandler Prompt;

        /// <summary>
        /// Occurs after the compliance model has started.
        /// </summary>
        event ModelingEventHandler ModelingStarted;
        /// <summary>
        /// Occurs after the compliance model has stopped, but did not complete successfully. This typically indicates
        /// that the user has aborted the modeling process or an exception in the code has occurred.
        /// </summary>
        event ModelingEventHandler ModelingStopped;
        /// <summary>
        /// Occurs after the compliance model has completed successfully.
        /// </summary>
        event ModelingEventHandler ModelingCompleted;
        /// <summary>
        /// Occurs after the compliance model has started, stopped, or completed. This event is generated alongside
        /// <see cref="ModelingStarted"/>, <see cref="ModelingStopped"/>, and <see cref="ModelingCompleted"/> events.
        /// The <see cref="ModelingChanged"/> event also occurs when a model start or stop has been requested by the
        /// user.
        /// </summary>
        event ModelingEventHandler ModelingChanged;

        /// <summary>
        /// Occurs before the processing of a single scenario (along with any pre-processing) has started.
        /// </summary>
        event ModelingProgressEventHandler ScenarioStarted;
        /// <summary>
        /// Occurs after the processing of a single scenario (along with any post-processing) has completed.
        /// </summary>
        event ModelingProgressEventHandler ScenarioCompleted;
        /// <summary>
        /// Occurs before the processing of a single iteration (along with any pre-processing) has started.
        /// </summary>
        event ModelingProgressEventHandler IterationStarted;
        /// <summary>
        /// Occurs after the processing of a single iteration (along with any post-processing) has completed.
        /// </summary>
        event ModelingProgressEventHandler IterationCompleted;
        /// <summary>
        /// Occurs before the processing of a single model year (along with any pre-processing) has started.
        /// </summary>
        event ModelingProgressEventHandler ModelYearStarted;
        /// <summary>
        /// Occurs after the processing of a single model year (along with any post-processing) has completed.
        /// </summary>
        event ModelingProgressEventHandler ModelYearCompleted;
        /// <summary>
        /// Occurs before the processing of a single manufacturer (along with any pre-processing) has started.
        /// </summary>
        event ModelingProgressEventHandler ManufacturerStarted;
        /// <summary>
        /// Occurs after the processing of a single manufacturer (along with any post-processing) has completed.
        /// </summary>
        event ModelingProgressEventHandler ManufacturerCompleted;

        #endregion

        #region <<< Methods >>>

        /// <summary>
        /// Creates a new instance with the same underlying type as this <see cref="ICompliance"/>.
        /// </summary>
        /// <returns>
        /// A new <see cref="ICompliance"/> object with the same underlying type as the current instance.
        /// </returns>
        ICompliance CreateNew();

        /// <summary>
        /// Validates the modeling data and settings and returns the string containing validation errors. If there were
        /// no validation errors, the return value will be an empty string.
        /// </summary>
        /// <param name="data">The modeling data to use for compliance modeling.</param>
        /// <param name="settings">The modeling settings to use for compliance modeling.</param>
        /// <returns>
        /// An error string containing any validation errors, or an <see cref="string.Empty"/> string, if no errors
        /// were encountered.
        /// </returns>
        string Validate(IIndustry data, ModelingSettings settings);

        /// <summary>
        /// Starts compliance modeling in a new thread, using the specified modeling data and settings.
        /// </summary>
        /// <param name="data">The modeling data to use for compliance modeling.</param>
        /// <param name="settings">The modeling settings to use for compliance modeling.</param>
        /// <remarks>
        /// The compliance model should always be started in a separate thread.
        /// </remarks>
        void Start(IIndustry data, ModelingSettings settings);

        /// <summary>
        /// Suspends the calling thread until the compliance model thread terminates.
        /// </summary>
        /// <remarks>
        /// The compliance model should always be started in a separate thread. If, however, the compliance model was
        /// started on the same thread as the caller, this method should return immediately.
        /// </remarks>
        void WaitForCompletion();

        /// <summary>
        /// Stops all threads spawned by this <see cref="ICompliance"/> instance, and terminates compliance modeling
        /// immediately.
        /// </summary>
        void Stop();

        /// <summary>
        /// Stops all threads spawned by this <see cref="ICompliance"/> instance, and terminates compliance modeling,
        /// optionally waiting for the pending operations to complete.
        /// </summary>
        /// <param name="stopWhenReady">
        ///     If true, specifies that the pending operations will be completed prior to stopping the modeling
        ///     process; otherwise, modeling will be terminated immediately.
        /// </param>
        void Stop(bool stopWhenReady);

        /// <summary>
        /// Returns the compliance modeling data for the specified scenario.
        /// </summary>
        /// <param name="scen">The scenario for which to obtain the compliance modeling data.</param>
        /// <returns>
        /// An <see cref="IIndustry"/> objects that contains compliance modeling data for the specified scenario.
        /// </returns>
        /// <remarks>
        /// If the compliance model has not yet been run, or has not started processing the specific scenario the
        /// return value may be null.
        /// </remarks>
        IIndustry GetData(Scenario scen);

        /// <summary>
        /// Returns the effects modeling data for the specified scenario.
        /// </summary>
        /// <param name="scen">The scenario for which to obtain the effects modeling data.</param>
        /// <returns>
        /// An <see cref="IAnnualValue{ModelingEffects}"/> object that contains effects modeling data for the specified
        /// scenario.
        /// </returns>
        /// <remarks>
        /// If the compliance model has not yet been run, or has not started processing the specific scenario the
        /// return value may be null.
        /// </remarks>
        IAnnualValue<ModelingEffects> GetEffectsData(Scenario scen);

        #endregion

        #region <<< Properties >>>

        /// <summary>Gets or sets the additional user specified notes associated with the compliance model.</summary>
        string UserNotes { get; set; }
        /// <summary>Gets or sets the user specified keywords (or tags) associated with the compliance model.</summary>
        string UserKeywords { get; set; }

        /// <summary>
        /// Gets the product plan modeling data associated with this <see cref="ICompliance"/> instance, which is the
        /// unaltered input data being used for compliance modeling.
        /// </summary>
        IIndustry Data { get; }
        /// <summary>
        /// Gets the modeling settings associated with this <see cref="ICompliance"/> instance, which are the settings
        /// being used for compliance modeling.
        /// </summary>
        ModelingSettings Settings { get; }

        /// <summary>Gets the object to use for writing log files generated during compliance modeling.</summary>
        ILogger LogWriter { get; }
        /// <summary>Gets the object to use for generating modeling reports for the compliance model.</summary>
        IReporter ReportGenerator { get; }

        /// <summary>Gets the current state of the modeling process.</summary>
        ModelingState State { get; }

        /// <summary>Gets whether the user has requested to start compliance modeling.</summary>
        bool StartRequested { get; }
        /// <summary>Gets whether the compliance model is currently running.</summary>
        bool Running { get; }
        /// <summary>Gets whether the user has requested to stop compliance modeling.</summary>
        bool StopRequested { get; }
        /// <summary>
        /// Gets whether the compliance model has been stopped (either the user has requested to stop or an error has
        /// occurred during modeling).
        /// </summary>
        bool Stopped { get; }
        /// <summary>Gets whether the compliance model has completed successfully.</summary>
        bool Completed { get; }
        /// <summary>Gets whether the compliance model has stopped or completed.</summary>
        bool StoppedOrCompleted { get; }

        /// <summary>Gets the current modeling progress, or null if compliance modeling has not started.</summary>
        IModelingProgress Progress { get; }

        /// <summary>Gets the timestamp of when the modeling process was started (or restarted).</summary>
        DateTime StartTime { get; }
        /// <summary>Gets the timestamp of when the modeling process has stopped or completed.</summary>
        DateTime StopTime { get; }

        /// <summary>
        /// Gets the amount of time, in milliseconds, that the compliance model has been running thus far or since it
        /// was last restarted.
        /// </summary>
        long Runtime { get; }

        /// <summary>Gets the minimum historic year available for effects modeling.</summary>
        int MinHistoricYear { get; }
        /// <summary>Gets the minimum year available for compliance modeling.</summary>
        int MinYear { get; }
        /// <summary>Gets the maximum year available for compliance modeling.</summary>
        int MaxYear { get; }

        /// <summary>
        /// Gets the last error message generated by the compliance model, or null, if no errors were encountered
        /// during modeling.
        /// </summary>
        string LastErrorMessage { get; }
        /// <summary>
        /// Gets the last exception thrown during model calculation, or null, if no errors were encountered during
        /// modeling.
        /// </summary>
        Exception LastException { get; }

        #endregion
    }
}
