using DeleteMe.ViewModels;
using System;
using System.Globalization;
using System.Reflection;
using TinyIoC;
using Xamarin.Forms;

namespace DeleteMe.Services
{
    public static class ViewModelLocator
    {
        private static TinyIoCContainer _container;

        public static readonly BindableProperty AutoWireViewModelProperty =
            BindableProperty.CreateAttached("AutoWireViewModel", 
                typeof(bool), 
                typeof(ViewModelLocator), 
                default(bool), 
                propertyChanged: OnAutoWireViewModelChanged);

        public static bool GetAutoWireViewModel(BindableObject bindable)
        {
            return (bool)bindable.GetValue(ViewModelLocator.AutoWireViewModelProperty);
        }

        public static void SetAutoWireViewModel(BindableObject bindable, bool value)
        {
            bindable.SetValue(ViewModelLocator.AutoWireViewModelProperty, value);
        }

        public static bool UseMockService { get; set; }

        static ViewModelLocator()
        {
            _container = new TinyIoCContainer();
            //View Models - by default, TinyIoC will register concrete classes as multi-instance (each one gets one?)
            _container.Register<MainPageViewModel>();
            _container.Register<TwoViewModel>();
            _container.Register<ParameterizedViewModel>();

            //Services - by default, TinyIoC will register interface registrations as singltons (each one gets the same one)
            _container.Register<INavigationService, NavigationService>();
            #region Register additional services
            //_container.Register<IDialogService, DialogService>();
            //_container.Register<ISettingsService, SettingsService>();
            #endregion
        }

        public static void UpdateDependencies(bool useMockServices)
        {
            //See eshop to see what they did with mocks - otherwise we don't have mocks here. 
        }
        public static void RegisterSingleton<TInterface, T>() where TInterface : class where T : class, TInterface
        {
            _container.Register<TInterface, T>().AsSingleton();
        }

        public static T Resolve<T>() where T : class
        {
            return _container.Resolve<T>();
        }


        private static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var view = bindable as Element;
            if (view == null)
            {
                return;
            }

            var viewType = view.GetType();
            var viewName = viewType.FullName.Replace(".Views.", ".ViewModels.");
            var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
            var viewModelName = string.Format(CultureInfo.InvariantCulture, "{0}Model, {1}", viewName, viewAssemblyName);

            var viewModelType = Type.GetType(viewModelName);
            if (viewModelType == null)
            {
                return;
            }
            var viewModel = _container.Resolve(viewModelType);
            view.BindingContext = viewModel;
        }
    }
}
