using System;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using nft.framework;
using nft.win32util;

namespace nft.util
{
	public enum UIMessageType{ normal, info, warning, alert, question, hint }
	public enum UIQueryType{ ok_cancel, yes_no }
	public enum UIInformLevel{ minor, normal, severe }

	/// <summary>
	/// utilities about display message, can get simple answer.
	/// </summary>
	public class UIUtil
	{
		static private IMessageUIHandler handler = new SilentHandler();
		static private ImageList msgIcons = null;

		private UIUtil()
		{
		}

		static public ImageList MsgTypeIcons 
		{
			get
			{
				if(msgIcons==null)
				{
					msgIcons = new ImageList();
					msgIcons.ImageSize = new Size(16,16);
					msgIcons.Images.Add( Image.FromFile(Directories.SystemResourceDir+"null.bmp"));
					msgIcons.Images.Add( Image.FromFile(Directories.SystemResourceDir+"info.ico"));
					msgIcons.Images.Add( Image.FromFile(Directories.SystemResourceDir+"warning.ico"));
					msgIcons.Images.Add( Image.FromFile(Directories.SystemResourceDir+"error.ico"));
					msgIcons.Images.Add( Image.FromFile(Directories.SystemResourceDir+"question.ico"));
					msgIcons.Images.Add( Image.FromFile(Directories.SystemResourceDir+"hint.ico"));
				}
				return msgIcons;
			}
		}

		static public void OpenURLByBrowser(string url)
		{
			// Because shell execuse doesn't work
			// we have to specify executing module directory
			ProcessStartInfo info = new ProcessStartInfo();
			// get default browser (exe) path
			String val = RegistryHelper.ReadKey(@"HKEY_CLASSES_ROOT\http\shell\open\command","");
			if(val.StartsWith("\""))
			{
				int n = val.IndexOf("\"",1);
				info.FileName = val.Substring(1,n-1);
				info.Arguments = val.Substring(n+1);
			}
			else
			{
				string[] a = val.Split(new char[]{' '});
				info.FileName = a[0];
				info.Arguments = val.Substring(a[0].Length+1);
			}
			// Specifies working directory is necessary to run browser successfuly.
			info.WorkingDirectory = Path.GetDirectoryName(info.FileName);
			
			info.Arguments += url;
			Debug.WriteLine(info.FileName,"OpenBrowser");
			Debug.WriteLine(info.WorkingDirectory,"OpenBrowser");
			Debug.WriteLine(info.Arguments,"OpenBrowser");
			Process.Start(info);
		}

		static public void Message(string text,UIMessageType type,UIInformLevel level)
		{
			handler.ShowMessage(text,type,level);
		}
		static public bool YesNoMessage(string text)
		{
			return handler.ShowQueryMessage(text,UIQueryType.yes_no,UIMessageType.question,UIInformLevel.normal);			
		}
		static public bool ConfirmMessage(string text,UIMessageType type,UIInformLevel level)
		{
			return handler.ShowQueryMessage(text,UIQueryType.ok_cancel,UIMessageType.question,UIInformLevel.normal);			
		}
        
        /// <summary>
        /// Show Exception Detail Form. Should throw again when true returns.
        /// ex. if(UIUtil.ShowException(text,caused,level)) throw;
        /// </summary>
        /// <param name="text"></param>
        /// <param name="caused"></param>
        /// <param name="level"></param>
        /// <returns>Should throw again if true returns</returns> 
        static public bool ShowException(string text,Exception caused,UIInformLevel level)
		{
			return handler.ShowException(text,caused,level);
		}

		static public void SetHandler(IMessageUIHandler new_handler)
		{
			if(handler!=null)
				handler.Release();
			if(new_handler==null)
				handler = new SilentHandler();
			else
				handler = new_handler;
		}

		private class SilentHandler : IMessageUIHandler
		{
			public void ShowMessage(string text,UIMessageType type,UIInformLevel level)
			{
				Debug.WriteLine(text);
			}
			public bool ShowException(string text,Exception caused,UIInformLevel level)
			{
                Debug.WriteLine(text);
                DumpException(caused);
                return ShowErrorMessageBox(null, text, caused);
			}
			public bool ShowQueryMessage(string text,UIQueryType query,UIMessageType type,UIInformLevel level)
			{
				return MessageBox.Show(text,"NeoFreeTrain",MessageBoxButtons.YesNo)==DialogResult.Yes;
			}
			public void Release()
			{
			}
		}

        public static void DumpException(Exception ex) {
            if (ex.InnerException != null) {
                DumpException(ex.InnerException);
                Debug.WriteLine("----wrapped by----");
            }
            Debug.WriteLine(ex.GetType().Name + ":" + ex.Message);
            if(ex.HelpLink!=null) Debug.WriteLine(ex.HelpLink);
            Debug.WriteLine(ex.StackTrace);
        }

		public static bool ShowErrorMessageBox(IWin32Window owner, string msg, Exception e )
		{
			Assembly asm = Assembly.LoadFrom(Directories.AppBaseDir+"NFT.UI.DLL");
			Type t = asm.GetType("nft.ui.system.ErrorMessageBox");
            BindingFlags flags = BindingFlags.Public|BindingFlags.Static|BindingFlags.InvokeMethod;
            DialogResult ret = (DialogResult)t.InvokeMember("Show", flags, null, null, new object[] { owner, msg, e });
            if (DialogResult.Abort==ret && Main.mainFrame!=null) {
                string msg2 =I18n.T("Are you sure to exit 'NeoFT'?");
                DialogResult r2 = MessageBox.Show(null, msg2, "NeoFT", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (r2 == DialogResult.Yes) {
                    Environment.Exit(0);
                }
            }
            return DialogResult.Retry == ret;
		}
	}

	public interface IMessageUIHandler
	{
		void ShowMessage(string text,UIMessageType type,UIInformLevel level);        
		bool ShowException(string text,Exception caused,UIInformLevel level);
		bool ShowQueryMessage(string text,UIQueryType query,UIMessageType type,UIInformLevel level);
		void Release();
	}
}
