using System.Linq;
using System.Web;
using System.Web.Hosting;
using Hangfire;
using Hangfire.Dashboard;
using LeafWeb.WebCms.App_Start;
using LeafWeb.WebCms.Services.PiscalQueue;
using Microsoft.Owin;
using Owin;
using Umbraco.Core.Security;
using Umbraco.Web;
using ConfigurationManager = System.Configuration.ConfigurationManager;

[assembly: OwinStartup(typeof(LeafwebOwinStartup))]

namespace LeafWeb.WebCms.App_Start
{
	public class LeafwebOwinStartup : UmbracoDefaultOwinStartup
	{
		public new void Configuration(IAppBuilder app)
		{
			base.Configuration(app);
			new HangfireStartup().Configuration(app);
		}
	}

	// https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/59500-Umbraco-and-Background-Tasks
	public class HangfireStartup
	{
		private const string PiscalProcessQueue = "PiscalProcessQueue";

		public void Configuration(IAppBuilder app)
		{
			app.UseHangfireDashboard("/hangfire",
				new DashboardOptions
				{
					Authorization = new IDashboardAuthorizationFilter[]
					{
						//new LocalRequestsOnlyAuthorizationFilter(),
						new UmbracoAuthorizationFilter()
					}
				});

			SetupRecurringJobs();
		}

		private void SetupRecurringJobs()
		{
			var queueInterval = ConfigurationManager.AppSettings["ProcessQueueInterval"];
			// https://discuss.hangfire.io/t/how-to-create-cron-job-that-is-executing-every-15-minutes/533
			RecurringJob.AddOrUpdate<PiscalQueueManager>(PiscalProcessQueue, p => p.ProcessQueue(), queueInterval);
		}

		public static void TriggerPiscalProcessQueue()
		{
			RecurringJob.Trigger(PiscalProcessQueue);
		}
	}

	public class UmbracoAuthorizationFilter : IDashboardAuthorizationFilter
	{
		public bool Authorize(DashboardContext context)
		{
			// Ensure umbraco user if possible.
			var http = new HttpContextWrapper(HttpContext.Current);
			var ticket = http.GetUmbracoAuthTicket();
			http.AuthenticateCurrentRequest(ticket, true);

			var user = UmbracoContext.Current.Security.CurrentUser;

			if (user != null && user.AllowedSections.Contains("developer"))
			{
				return true;
			}

			return false;
		}
	}

	// http://docs.hangfire.io/en/latest/deployment-to-production/making-aspnet-app-always-running.html
	public class ApplicationPreload : IProcessHostPreloadClient
	{
		public void Preload(string[] parameters)
		{
			HangfireBootstrapper.Instance.Start();
		}
	}

	public class HangfireBootstrapper : IRegisteredObject
	{
		public static readonly HangfireBootstrapper Instance = new HangfireBootstrapper();

		private readonly object _lockObject = new object();
		private bool _started;

		private BackgroundJobServer _backgroundJobServer;

		private HangfireBootstrapper()
		{
		}

		public void Start()
		{
			lock (_lockObject)
			{
				if (_started) return;
				_started = true;

				HostingEnvironment.RegisterObject(this);

				// TODO: use Umbraco Connection string?
				// var cs = Umbraco.Core.ApplicationContext.Current.DatabaseContext.ConnectionString;

				GlobalConfiguration
					.Configuration
					.UseSqlServerStorage("LeafWebContext");
				// Specify other options here

				_backgroundJobServer = new BackgroundJobServer();
			}
		}

		public void Stop()
		{
			lock (_lockObject)
			{

				_backgroundJobServer?.Dispose();

				HostingEnvironment.UnregisterObject(this);
			}
		}

		void IRegisteredObject.Stop(bool immediate)
		{
			Stop();
		}
	}
}