using Catel.ApiCop;
using Catel.ApiCop.Listeners;
using Catel.Configuration;
using Catel.ExceptionHandling;
using Catel.IoC;
using Catel.Logging;
using Catel.MVVM;
using Catel.MVVM.Views;
using Catel.Reflection;
using Catel.Services;
using CatelSample.ViewModels.Interfaces;
using CatelSample.Views;
using CatelSample.Views.Services;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Threading;

namespace CatelSample
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        private static readonly ILog Log = LogManager.GetCurrentClassLogger();

        protected CatelSample.IContext Context;

        public App()
            : base()
        {
#if DEBUG
            //LogManager.AddDebugListener();
#endif
            Log.Info("Starting application");

            // To force the loading of all assemblies at startup, uncomment the lines below:

            Log.Info("Preloading assemblies");
            var directory = typeof(MainWindow).Assembly.GetDirectory();
            AppDomain.CurrentDomain.PreloadAssemblies(directory);

            //Log.Info("Allow 404 errors in Flurl");
            //FlurlHttp.Configure(c =>
            //{
            //    c.DefaultTimeout = TimeSpan.FromSeconds(30);

            //    // Statuses (in addition to 2xx) that won't throw exceptions.
            //    // Set to "*" to allow everything.
            //    c.AllowedHttpStatusRange = "404";
            //});

            ServiceLocator.Default.RegisterType<IContext, Context>();
            ServiceLocator.Default.RegisterType<ITabService, TabService>();

            // Load LanguageResources
            IDependencyResolver dependencyResolver = this.GetDependencyResolver();
            Context = dependencyResolver.Resolve<IContext>();
            Context.ExceptionService = dependencyResolver.Resolve<IExceptionService>();
            Context.Dialogs = dependencyResolver.Resolve<IMessageService>();
            Context.Settings = dependencyResolver.Resolve<IConfigurationService>();
            Context.Resources = dependencyResolver.Resolve<ILanguageService>();
            Context.Dispatcher = dependencyResolver.Resolve<IDispatcherService>();
            Context.WaitService = dependencyResolver.Resolve<IPleaseWaitService>();
            Context.TabService = dependencyResolver.Resolve<ITabService>();
            Context.ViewManager = dependencyResolver.Resolve<IViewManager>();

            //Register exception handlers
            Context.ExceptionService.Register<NotImplementedException>(ex =>
            {
                Context.Dialogs.ShowInformationAsync(Context.Resources.GetString("FutureModule"));
            });

            //Context.ExceptionService.Register<Flurl.Http.FlurlHttpException>(ex =>
            //{
            //    Context.Dialogs.ShowInformationAsync(ex.Message);
            //});

            Context.ExceptionService.Register<Exception>(ex =>
            {
                Context.Dialogs.ShowInformationAsync(Context.Resources.GetString("EX_DEFAULT"));
            });

            Log.Info("Initialize application-wide context");

            //var modelLocator = ServiceLocator.Default.ResolveType<IViewModelLocator>();
            //modelLocator.NamingConventions.Add("CatelSample.ViewModels.Commodities.Details.[VW]ViewModel");
            //modelLocator.NamingConventions.Add("CatelSample.ViewModels.Commodities.[VW]ViewModel");
            //modelLocator.NamingConventions.Add("CatelSample.ViewModels.Relations.Details.[VW]ViewModel");
            //modelLocator.NamingConventions.Add("CatelSample.ViewModels.Relations.[VW]ViewModel");

            //var viewLocator = ServiceLocator.Default.ResolveType<IViewLocator>();
            //viewLocator.NamingConventions.Add("CatelSample.Views.Authentication.[VM]Window");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Accounting.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Accounting.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Accounting.Details.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Accounting.Editors.[VM]Window");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Commodities.Details.[VM]Control");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Commodities.Editors.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Commodities.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Commodities.[VM]View");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Documents.Editors.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Documents.[VM]View");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Library.Details.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Library.Editors.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Library.[VM]Window");

            //viewLocator.NamingConventions.Add("CatelSample.Views.MasterData.Details.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.MasterData.Editors.[VM]Window");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Relations.Details.[VM]Control");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Relations.Editors.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Relations.[VM]Window");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Relations.[VM]View");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Sales.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Sales.[VM]Window");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Schedule.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Schedule.Details.[VM]View");
            //viewLocator.NamingConventions.Add("CatelSample.Views.Schedule.Editors.[VM]Window");

            //viewLocator.NamingConventions.Add("CatelSample.Views.Reporting.[VM]Window");

            Log.Info("Initializing UIService");
            Context.Visualizer = dependencyResolver.Resolve<IUIVisualizerService>();

            App.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
        }

        private async void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            await Context.ExceptionService.ProcessAsync(() =>
            {
                e.Handled = true;

                throw e.Exception;
            });
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

            Log.Info("Calling base.OnStartup");
            base.OnStartup(e);
        }

        protected override void OnExit(ExitEventArgs e)
        {
            // Get advisory report in console
            ApiCopManager.AddListener(new ConsoleApiCopListener());
            ApiCopManager.WriteResults();

            base.OnExit(e);
        }
    }
}