using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Medivators.Common;
using Medivators.Common.Logging;

namespace Medivators.Reporting
{
	public class App
	{
		private static ILogProvider _pLog = null;
		private static ILogProvider _sLog = null;
		static App _instance = null;
		private static Dictionary<Enums.Forms, frmBase> _openForms = new Dictionary<Enums.Forms,frmBase>();

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main()
		{
			try
			{
				Application.EnableVisualStyles();
				Application.SetCompatibleTextRenderingDefault(false);

				// put up splash
				dlgSplash splash = new dlgSplash();
				splash.Show();
				Application.DoEvents();

				//	load settings
				TextSettings.GetInstance().Load(Constants.MedivatorsProgramFiles,
												Constants.MedivatorsSettingsFile);

				//	start log providers and error handling 
				InitLogProviders();
				Log.GetInstance().Provider = _pLog;
				ErrorHandler.GetInstance().Initialize(_pLog, _sLog);
				Log.GetInstance().WriteLog("Medivators Reporting reports Logs and ErrorHandler initialized");

				//	initialize settings
				TextSettings.GetInstance().Load();

				//	start user out with the Cycles form
				frmCycles frm = new frmCycles();
				frm.Show();
				_openForms.Add(Enums.Forms.Cycles, frm);

				splash.Dispose();

				Application.Run();

				//	save settings
				TextSettings.GetInstance().Save();
			}
			catch (Exception ex)
			{
				using (dlgError dlg = new dlgError())
				{
					dlg.Message = "Medivators.Reporting has encountered an error and must close.";
					dlg.Details = ex.ToString();
					dlg.ShowDialog();
				}
				ErrorHandler.GetInstance().LogException("Medivators Reporting Main:", ex);
			}
		}

		public static App GetInstance()
		{
			if (_instance == null)
				_instance = new App();
			return _instance;
		}

		public static void Exit()
		{
			foreach (frmBase frm in _openForms.Values)
				frm.Dispose();
			_openForms.Clear();
			Properties.Settings.Default.Save();
			Application.Exit();
		}
		public static void OpenForm(Enums.Forms Form)
		{
			if (_openForms == null)
				_openForms = new Dictionary<Enums.Forms, frmBase>();

			//	focus and visible the desired form
			if (_openForms.ContainsKey(Form))
			{
				if (_openForms[Form].WindowState == FormWindowState.Minimized)
					_openForms[Form].WindowState = FormWindowState.Normal;
				_openForms[Form].Visible = true;
				_openForms[Form].Focus();
			}
			else
			{
				//	desired form has not been cached.
				//	instantiate and cache it now. 
				frmBase frm = null;
				switch (Form)
				{
					//TODO: augment as new forms are added
					case Enums.Forms.Admin:
						if ( CheckAdminPassword() )
							frm = new frmAdmin();
						break;
					case Enums.Forms.Cycles:
						frm = new frmCycles();
						break;
					case Enums.Forms.Logs:
						frm = new frmLogs();
						break;
				}
				if (frm != null)
				{
					frm.Show();
					_openForms.Add(Form, frm);
				}
			}
		}
		public static void CloseForm(Enums.Forms Form)
		{
			if (_openForms == null)
				_openForms = new Dictionary<Enums.Forms, frmBase>();
			if (_openForms.ContainsKey(Form))
			{
				_openForms[Form].Dispose();
			}
			_openForms.Remove(Form);
			if (_openForms.Count == 0)
				App.Exit();
		}

		public static void ShowError(string message, Exception ex)
		{
			ShowError(message, ex.ToString());
		}
		public static void ShowError(string message, string details)
		{
			using (dlgError dlg = new dlgError())
			{
				dlg.Message = message;
				dlg.Details = details;
				dlg.ShowDialog();
			}
		}

		private static void InitLogProviders()
		{
			//	init log providers
			if (_sLog == null)
			{
				_sLog = new ApplicationLog();
				_sLog.Initialize();
			}
			if (_pLog == null)
			{
				_pLog = new TextLog(Utilities.PathSlash(Constants.MedivatorsProgramFiles) +
									Utilities.PathSlash("logs") +
									Utilities.GetAppName() +
									".log");
				_pLog.Initialize();
			}
		}

		private static bool CheckAdminPassword()
		{
			using (dlgAdminPass dlg = new dlgAdminPass())
			{
				dlg.ShowDialog();
				if (dlg.DialogResult == DialogResult.OK)
					return true;
				else
					return false;
			}
		}
	}
}