using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace CustomForms
{
	public enum EventType
	{
		Information,
		Warning,
		Error
	} ;

	public delegate void ShowEventDelegate(string Text, EventType EventType);

	public delegate void SimpleDelegate();

	public partial class NotifyForm : Form
	{
		private readonly Control Main;
		private readonly int MaxShowingTime;
		private readonly string SoundDir;
		private new bool Modal;
		private int StartShowTime;

		public NotifyForm(string SoundDir, Control MainWnd, int maxshowingTimeSeconds)
		{
			InitializeComponent();
			Main = MainWnd;
			MaxShowingTime = maxshowingTimeSeconds;
			this.SoundDir = SoundDir;
		}

		private void OkBtn_Click(object sender, EventArgs e)
		{
			if (InvokeRequired)
				BeginInvoke(new SimpleDelegate(Hide));
			else
				Hide();
		}

		private void ShowInternal(string EventText, EventType EventType)
		{
			StartShowTime = Environment.TickCount;
			if (Main != null)
			{
				int X = Main.Left + (Main.Width / 2 - Width / 2);
				int Y = Main.Top + (Main.Height / 2 - Height / 2);
				Left = X;
				Top = Y;
			}
			Sound SS;
			ComponentResourceManager resources = new ComponentResourceManager(typeof(NotifyForm));
			switch (EventType)
			{
				case EventType.Information:
					Text = "ÈÍÔÎÐÌÀÖÈß";
					SS = new Sound(SoundImages.NotifySound);
					SS.Play();
					break;
				case EventType.Warning:
					Text = "ÏÐÅÄÓÏÐÅÆÄÅÍÈÅ";
					SS = new Sound(SoundImages.WarningSound);
					SS.Play();
					break;
				case EventType.Error:
					Text = "ÎØÈÁÊÀ";
					SS = new Sound(SoundImages.ErrorSound);
					SS.Play();
					break;
			}

			TextLbl.Text = EventText;
			if (ImageList.Images.Count > (int) EventType)
				PictureBox.Image = ImageList.Images[(int) EventType];
			try
			{
				if (!Modal)
					if (!Visible)
					{
						Show(Main);
						StartShowTime = Environment.TickCount;
					}
					else
					{
						//Visible = false;
						//base.Show(Main);
					}
				else
					ShowDialog(Main);
			}
			catch
			{
			}
		}

		public void Show(string EventText, EventType EventType)
		{
			if (InvokeRequired || !Application.MessageLoop)
			{
				BeginInvoke(new ShowEventDelegate(ShowInternal), new object[] {EventText, EventType});
			}
			else
			{
				ShowInternal(EventText, EventType);
			}
		}

		public void Show(string EventText)
		{
			Show(EventText, EventType.Error);
		}

		public void Show(string EventText, bool modal)
		{
			Modal = modal;
			Show(EventText, EventType.Error);
			Modal = false;
		}

		private void timer_Tick(object sender, EventArgs e)
		{
			if (Visible)
			{
				if (MaxShowingTime != 0)
				{
					if (Environment.TickCount - StartShowTime > MaxShowingTime * 1000)
						OkBtn_Click(null, null);
				}
			}
		}
	}

	public class Sound
	{
		private byte[] m_soundBytes;
		private string m_fileName;

		private enum Flags
		{
			SND_SYNC = 0x0000,  /* play synchronously (default) */
			SND_ASYNC = 0x0001,  /* play asynchronously */
			SND_NODEFAULT = 0x0002,  /* silence (!default) if sound not found */
			SND_MEMORY = 0x0004,  /* pszSound points to a memory file */
			SND_LOOP = 0x0008,  /* loop the sound until next sndPlaySound */
			SND_NOSTOP = 0x0010,  /* don't stop any currently playing sound */
			SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
			SND_ALIAS = 0x00010000, /* name is a registry alias */
			SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
			SND_FILENAME = 0x00020000, /* name is file name */
			SND_RESOURCE = 0x00040004  /* name is resource name or atom */
		}

		[DllImport("winmm.dll", EntryPoint = "PlaySound", SetLastError = true)]
		private extern static int PlaySound(string szSound, IntPtr hMod, int flags);

		[DllImport("winmm.dll", EntryPoint = "PlaySound", SetLastError = true)]
		private extern static int PlaySoundBytes(byte[] szSound, IntPtr hMod, int flags);

		/// <summary>
		/// Construct the Sound object to play sound data from the specified file.
		/// </summary>
		public Sound(string fileName)
		{
			m_fileName = fileName;
		}

		/// <summary>
		/// Construct the Sound object to play sound data from the specified stream.
		/// </summary>
		public Sound(Stream stream)
		{
			try
			{
				// read the data from the stream
				m_soundBytes = new byte[stream.Length];
				stream.Read(m_soundBytes, 0, (int) stream.Length);
			}catch{}
		}

		/// <summary>
		/// Construct the Sound object to play sound data from the specified byte array.
		/// </summary>
		public Sound(byte[] bytes)
		{
			try
			{
				m_soundBytes = bytes;
			}
			catch { }
		}
		/// <summary>
		/// Play the sound
		/// </summary>
		public void Play()
		{
			// if a file name has been registered, call WCE_PlaySound,
			//  otherwise call WCE_PlaySoundBytes
			if (m_fileName != null)
				PlaySound(m_fileName, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_FILENAME));
			else
				PlaySoundBytes(m_soundBytes, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_MEMORY));
		}
	}

	public static class SoundImages
	{
		public static byte[] ErrorSound;
		public static byte[] WarningSound;
		public static byte[] NotifySound;

		static SoundImages()
		{
			ErrorSound = GetHexBytes(ErrorStr);
			WarningSound = GetHexBytes(WarningStr);
			NotifySound = GetHexBytes(NotifyStr);
		}
		private static byte[] GetHexBytes(string s)
		{
			byte[] res = new byte[0];
			if(!string.IsNullOrEmpty(s))
			try
			{
				res = new byte[s.Length / 2];
				StringBuilder SB;
				for (int i = 0; i < res.Length; i++)
				{
					SB = new StringBuilder(2);
					SB.Append(s[i * 2]).Append(s[i * 2 + 1]);
					res[i] = byte.Parse(SB.ToString(), NumberStyles.HexNumber);
				}
			}
			catch {
				res = new byte[0]; }
			return res;
		}
		#region Sound Strings
		private static string WarningStr =
			"[encoded data, 16200 characters]";

		private static string ErrorStr =
			"[encoded data, 75344 characters]";

		private static string NotifyStr =
			"[encoded data, 18936 characters]";
		#endregion
	}

}