using System;

using Volpe.Cafe.Logging;
using Volpe.Cafe.MarketData.Design;
using Volpe.Cafe.ModelSettings;

namespace Volpe.Cafe.DfsSrModels.SalesEstimators
{
    /// <summary>
    /// Provides support for creating <see cref="ISalesEstimator"/> objects.
    /// </summary>
    [Serializable]
    public static class SalesEstimatorFactory
    {
        /// <summary>
        /// Returns a <see cref="ISalesEstimator"/> based on the configuration options in the specified modeling
        /// settings object, and using the specified industry data, modeling settings, and log writer.
        /// </summary>
        /// <inheritdoc cref="SalesEstimatorBase(IIndustry, ModelingSettings, ILogger)" path="/param"/>
        /// <inheritdoc cref="SalesEstimatorBase(IIndustry, ModelingSettings, ILogger)" path="/exception"/>
        public static ISalesEstimator CreateSalesEstimator(IIndustry data, ModelingSettings settings, ILogger logWriter)
        {
            return CreateSalesEstimator(data, settings, logWriter, settings.RuntimeSettings.SalesEstimator);
        }

        private static ISalesEstimator CreateSalesEstimator(
            IIndustry data, ModelingSettings settings, ILogger logWriter, SalesEstimator salesEstimatorMode)
        {
            switch (salesEstimatorMode) {
                case SalesEstimator.FixedForecast:
                    return new FixedForecast(data, settings, logWriter);

                case SalesEstimator.UserDefinedForecast:
                    return new UserDefinedForecast(data, settings, logWriter);

                case SalesEstimator.NominalForecast:
                    return new NominalForecastEstimator(data, settings, logWriter);

                case SalesEstimator.PriceElasticity:
                    return new PriceElasticitySalesEstimator(data, settings, logWriter, GetReferenceSalesEstimator());

                default:
                    throw new ArgumentException("Invalid sales estimator selected.");
            }

            ISalesEstimator GetReferenceSalesEstimator()
            {
                var refMode = settings.RuntimeSettings.ReferenceSalesEstimator;
                if (refMode.IsPriceElasticity()) {
                    throw new ArgumentException("Invalid sales estimator selected.");
                }

                return CreateSalesEstimator(data, settings, logWriter, refMode);
            }
        }

    }
}
