using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace CM2
{
	[ClassInterface(ClassInterfaceType.None)]
	[Guid("C3A0A318-D7A1-444a-9F99-670FBD897E87")]
	public class CM2Vis_CsText : ICM2VisPlug
	{
		private const int	E_FAIL = unchecked((int)0x80004005);

		private Graphics	hDC;
		private Rectangle	rectangle;
		private Color		foregroundColor;
		private Color		backgroundColor;
		private Font		font;
		private FontStyle	fontStyle;
		private int			fontSize;
		private string		fontFamily;
		private string		outputString;
		private string		lastErrorMessage;
		

		#region Contructors

		public CM2Vis_CsText()
		{
		}

		#endregion


		#region ICM2VisPlug Members

		public void Name(out string name)
		{
			name = "CsText";
		}

		public void Version(out ushort version)
		{
			version = 0x000A;
		}

		public void RequiredCoreVersion(out ushort requiredCoreVersion)
		{
			requiredCoreVersion = 0x01D6;
		}

		public void GetLastErrorMsg(out string errorMessage)
		{
			if(this.lastErrorMessage == String.Empty)
				errorMessage = "No error";
			else
				errorMessage = this.lastErrorMessage;
		}

		public void GetInfoCount(out int infoCount)
		{
			infoCount = 3;
		}

		public void GetInfo(int index, out string infoName, out string infoValue)
		{
			infoName = null;
			infoValue = null;

			switch(index)
			{
				case 0:
					infoName = "Ported by";
					infoValue = "O. Westman";
					break;

				case 1:
					infoName = "Created";
					infoValue = "28th May 2004";
					break;

				case 2:
					infoName = "Original version by";
					infoValue = "C. Aaangel";
					break;

				default:
					this.lastErrorMessage = "Index out of bounds";
					Marshal.ThrowExceptionForHR(E_FAIL);
					break;
			}
		}

		public void SetDC(IntPtr hDC)
		{
			try
			{
				this.hDC = Graphics.FromHdc(hDC);
			}
			catch(Exception e)
			{
				this.lastErrorMessage = e.Message;
				Marshal.ThrowExceptionForHR(E_FAIL);
			}
		}

		public void SetDimensions(int x, int y, int width, int height)
		{
			this.rectangle = new Rectangle(x, y, width, height);
		}

		public void SetConfigString(string newConfigString)
		{
			string[] param = newConfigString.Split(new char[] {'|', '='});

			for(int i = 0; i < param.Length; i++)
			{
				if(String.Compare(param[i], "FONT", true) == 0)
				{
					this.fontFamily = param[++i];
				}
				else if(String.Compare(param[i], "SIZE", true) == 0)
				{
					this.fontSize = Convert.ToInt32(param[++i]);
				}
				else if(String.Compare(param[i], "COLOR", true) == 0)
				{
					this.foregroundColor = BorlandColorConverter.StringToColor(param[++i]);
				}
				else if(String.Compare(param[i], "BACKGROUND", true) == 0)
				{
					this.backgroundColor = BorlandColorConverter.StringToColor(param[++i]);
				}
				else if(String.Compare(param[i], "BOLD", true) == 0)
				{
					this.fontStyle = (param[++i].ToLower() == "yes") ? this.fontStyle | FontStyle.Bold : this.fontStyle ^= (this.fontStyle & FontStyle.Bold);
				}
				else if(String.Compare(param[i], "ITALIC", true) == 0)
				{
					this.fontStyle = (param[++i].ToLower() == "yes") ? this.fontStyle | FontStyle.Italic : this.fontStyle ^ (this.fontStyle & FontStyle.Italic);
				}
				else if(String.Compare(param[i], "UNDERLINE", true) == 0)
				{
					this.fontStyle = (param[++i].ToLower() == "yes") ? this.fontStyle | FontStyle.Underline : this.fontStyle ^ (this.fontStyle & FontStyle.Underline);
				}
			}
		}

		public void Redraw()
		{
			try
			{
				Font font = new Font(this.fontFamily, this.fontSize, this.fontStyle);
				this.hDC.FillRectangle(new SolidBrush(this.backgroundColor), this.rectangle);
				this.hDC.DrawString(this.outputString, font, new SolidBrush(this.foregroundColor), this.rectangle.Left - 1, this.rectangle.Top + 2);
			}
			catch(Exception e)
			{
				this.lastErrorMessage = e.Message;
				Marshal.ThrowExceptionForHR(E_FAIL);
			}
		}

		public void Update(byte sensorStyle, string newString, double newValue)
		{
			switch(sensorStyle)
			{
				case 0:
					this.outputString = newValue.ToString();
					break;
				case 1:
					this.outputString = newString;
					break;
				default:
					this.outputString = "Invalid sensor style #" + sensorStyle.ToString();
					break;
			}
		}

		[DllImport("msvcr70.dll", CallingConvention=CallingConvention.Cdecl)]
		private static extern uint _controlfp(uint n, uint mask);

		public void Init(IntPtr hDC)
		{
			// Apparently System.Drawing.Font throws arithmetic
			// error if FPU exceptions are unmasked.
			// Why are they unmasked? Is this only on my system?
			// I have no idea. I'll just revert it.
			_controlfp(0x8001F, 0x10);

			this.fontFamily = "Arial";
			this.fontSize = 10;
			this.fontStyle = FontStyle.Regular;
			this.foregroundColor = Color.White;
			this.backgroundColor = Color.Black;

			try
			{
				this.hDC = Graphics.FromHdc(hDC);
			}
			catch(Exception e)
			{
				this.lastErrorMessage = e.Message;
				Marshal.ThrowExceptionForHR(E_FAIL);
			}
		}

		public void Terminating()
		{
		}

		public void Setup()
		{
			System.Windows.Forms.MessageBox.Show("Nothing to setup.", "CsText", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
		}

		public void GetDefaultCount(out int count)
		{
			count = 4;
		}

		public void GetDefault(int index, out string name, out string defaultValue, out string description)
		{
			name = null;
			defaultValue = null;
			description = null;

			switch(index)
			{
				case 0:
					name = "font";
					defaultValue = "Arial";
					description = "The name of the font you wish to use";
					break;

				case 1:
					name = "size";
					defaultValue = "10";
					description = "Font size";
					break;

				case 2:
					name = "color";
					defaultValue = "clWhite";
					description = "Font color";
					break;

				case 3:
					name = "background";
					defaultValue = "blBlack";
					description = "Background color - Should be the color of the parent form";
					break;

				default:
					this.lastErrorMessage = "Index out of bounds";
					Marshal.ThrowExceptionForHR(E_FAIL);
					break;
			}
		}

		public void GetOptionalCount(out int count)
		{
			count = 3;
		}

		public void GetOptional(int index, out string name, out string defaultValue, out string description)
		{
			name = null;
			defaultValue = null;
			description = null;

			switch(index)
			{
				case 0:
					name = "bold";
					defaultValue = "No";
					description = "Make the font bold if set to \"Yes\"";
					break;

				case 1:
					name = "italic";
					defaultValue = "No";
					description = "Make the font italic if set to \"Yes\"";
					break;

				case 2:
					name = "underline";
					defaultValue = "No";
					description = "Make the font underlined if set to \"Yes\"";
					break;

				default:
					this.lastErrorMessage = "Index out of bounds";
					Marshal.ThrowExceptionForHR(E_FAIL);
					break;
			}
		}

		#endregion
	}
}
