using System;

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

namespace Volpe.Cafe.DfsSrModels.DfsModels
{
    /// <summary>
    /// Provides support for creating <see cref="IDfsModel"/> objects.
    /// </summary>
    [Serializable]
    public static class DfsModelFactory
    {
        /// <summary>
        /// Returns a <see cref="IDfsModel"/> 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="DfsModelBase(IIndustry, ModelingSettings, ILogger)" path="/param"/>
        /// <inheritdoc cref="DfsModelBase(IIndustry, ModelingSettings, ILogger)" path="/exception"/>
        public static IDfsModel CreateDfsModel(IIndustry data, ModelingSettings settings, ILogger logWriter)
        {
            return CreateDfsModel(data, settings, logWriter, settings.RuntimeSettings.DfsModel);
        }

        private static IDfsModel CreateDfsModel(
            IIndustry data, ModelingSettings settings, ILogger logWriter, DfsModel dfsModelMode)
        {
            switch (dfsModelMode) {
                case DfsModel.FixedFleetShares:
                    return new FixedFleetShares(data, settings, logWriter);

                case DfsModel.UserDefinedShares:
                    return new UserDefinedShares(data, settings, logWriter);

                case DfsModel.Experimental:
                    return new ExperimentalDfsModel(data, settings, logWriter);

                case DfsModel.PriceElasticity:
                    return new PriceElasticityDfsModel(data, settings, logWriter, GetReferenceDfsModel());

                default:
                    throw new ArgumentException("Invalid DFS model selected.");
            }

            IDfsModel GetReferenceDfsModel()
            {
                var refMode = settings.RuntimeSettings.ReferenceDfsModel;
                if (refMode.IsPriceElasticity()) {
                    throw new ArgumentException("Invalid DFS model selected.");
                }

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

    }
}
