using System;
using Ninject.Infrastructure;
using Ninject.Injection;
using Ninject.Planning.Bindings;
using Ninject.Syntax;

namespace Ninject.Moq
{
    /// <summary>
    ///   Extensions for the fluent binding syntax API.
    /// </summary>
    public static class ExtensionsForBindingSyntax
    {
        /// <summary>
        ///   Indicates that the service should be bound to a mocked instance of the specified type.
        /// </summary>
        /// <typeparam name = "T">The service that is being mocked.</typeparam>
        /// <param name = "builder">The builder that is building the binding.</param>
        public static IBindingWhenInNamedWithOrOnSyntax<T> ToMock<T>(this IBindingToSyntax<T> builder)
        {
            var haveBinding = builder as IHaveBinding;

            if (haveBinding == null)
                throw new NotSupportedException(
                    String.Format(
                        "The binding builder for {0} is of type {1}, which does not implement IHaveBinding and is therefore not extensible.",
                        typeof (T), builder.GetType()));

            IBinding binding = haveBinding.Binding;

            binding.ProviderCallback = ctx => new MockProvider(ctx.Kernel.Components.Get<IInjectorFactory>());

            return builder as IBindingWhenInNamedWithOrOnSyntax<T>;
        }
    }
}