using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Windows.Forms;
using System.Drawing;

using System.Xml;
using System.Xml.Serialization;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using D3D = Microsoft.DirectX.Direct3D;
using Vector3 = Microsoft.DirectX.Vector3;
using Vector2 = Microsoft.DirectX.Vector2;

namespace MhsModelCSharp
{

	/// <summary>
	/// Simple exception class to distinguish different types of file importing
	/// errors. Doesn't override a damn thing from exception.
	/// </summary>
	public class FieldTripImportFileLineCorruptException : Exception {}







	/// <summary>
	/// This is a type converter for Direct3D Vectors. The type converter
	/// can convert the x,y,z coordinates to and from a text string
	/// like "x,y,z" with whitespace all over. You 
	/// can use the TypeConverter attribute on properties
	/// that take/return Vector2s. Then when the runtime/reflection needs
	/// to convert back and forth from strings to vectors it will use this
	/// class. This is important for windows controls like PropertyGrids
	/// <remark>
	/// Vector2's are structs brought in via interop.
	///	They have no accessors/properties. They have methods instead.
	///	So the standard TypeConverter.GetProperties doesn't return anything. 
	///	You can still use the ConvertFrom w/ strings to edit in the grid though.
	///	</remark>
	///	<remark>
	///	This also makes it possible to have the Vector2 ink editors work directly
	///	in strings instead of multi parameter floats.
	///	</remark>
	/// </summary>

	public class D3DVector2TypeConverter
		: ExpandableObjectConverter
	{
		/// <summary>
		/// Vector2's are structs brought in via interop.
		/// They have no accessors/properties, they have methods instead
		/// So GetProperties doesn't return anything and hence we declare
		/// here that properties are unsupported by returning false. 
		/// You can still use the ConvertFrom w/ strings to edit. 
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		public override bool GetPropertiesSupported(ITypeDescriptorContext context)
		{
			return false;
		}


		/// <summary>
		/// A test method to see what this converter can convert 
		/// from. Which for us is just string
		/// </summary>
		/// <param name="context"></param>
		/// <param name="sourceType">The Type that you want to convert from</param>
		/// <returns></returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			//if( sourceType == typeof(string) )
			//	return true;

			if( sourceType == typeof(string[]) )
				return true;

			return base.CanConvertFrom (context, sourceType);
		}

		/// <summary>
		/// A test method to see what this converter can convert to. For us
		/// this is Vector2
		/// </summary>
		/// <param name="context"></param>
		/// <param name="destinationType">The Type that you want to conver to</param>
		/// <returns></returns>
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			//if( destinationType == typeof(Vector2) )
			//	return true;

			if( destinationType == typeof(Vector2[]) )
				return true;

			return base.CanConvertTo (context, destinationType);
		}

		/// <summary>
		/// Perform the actual conversion from string to Vector2
		/// </summary>
		/// <param name="context"></param>
		/// <param name="culture"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
		{
//			if( value is string)
//			{
//				string vectorString = (string) value;
//				string[] floatStrings = Regex.Split(vectorString,"\\s*,\\s*");
//				Vector2 vec = new Vector2(	float.Parse(floatStrings[0]),
//					float.Parse(floatStrings[1]));
//				return vec;
//			}

			if( value is string[])
			{
				string[] vectorStringArray = (string[]) value;
				Vector2[] vecs = new Vector2[vectorStringArray.Length];

				for(int i = 0; i < vectorStringArray.Length; i++)
				{
					string vectorString = vectorStringArray[i];
					string[] floatStrings = Regex.Split(vectorString,"\\s*,\\s*");
					vecs[i] = new Vector2(	float.Parse(floatStrings[0]),
											float.Parse(floatStrings[1]));
				}

				return vecs;
			}

			return base.ConvertFrom (context, culture, value);
		}

		/// <summary>
		/// Perform the actual conversion from Vector2 to string
		/// </summary>
		/// <param name="context"></param>
		/// <param name="culture"></param>
		/// <param name="value"></param>
		/// <param name="destinationType"></param>
		/// <returns></returns>
		public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
		{
//			if( destinationType == typeof(string) && value is Vector2 )
//			{
//				Vector2 v = (Vector2)value;
//				return v.X.ToString("000.00") + " , " + v.Y.ToString("000.00");
//			}

			if( destinationType == typeof(string[]) && value is Vector2[] )
			{
				Vector2[] vecs = (Vector2[])value;
				string[] strings = new string[vecs.Length];
				for( int i=0;i<vecs.Length;i++ )
				{
					strings[i] = vecs[i].X.ToString("000.00") + " , " + vecs[i].Y.ToString("000.00");
				}
				return strings;
			}

			return base.ConvertTo (context, culture, value, destinationType);
		}
	} // END D3DVector2TypeConverter














	/// <summary>
	/// This is a type converter for Direct3D Vectors. The type converter
	/// can convert the x,y,z coordinates to and from a text string
	/// like "x,y,z" with whitespace all over. You 
	/// can use the TypeConverter attribute on properties
	/// that take/return Vector3s. Then when the runtime/reflection needs
	/// to convert back and forth from strings to vectors it will use this
	/// class. This is important for windows controls like PropertyGrids
	/// <remark>
	/// Vector3's are structs brought in via interop.
	///	They have no accessors/properties. They have methods instead.
	///	So the standard TypeConverter.GetProperties doesn't return anything. 
	///	You can still use the ConvertFrom w/ strings to edit in the grid though.
	///	</remark>
	///	<remark>
	///	This also makes it possible to have the Vector3 ink editors work directly
	///	in strings instead of multi parameter floats.
	///	</remark>
	/// </summary>
	public class D3DVector3TypeConverter
		: ExpandableObjectConverter
	{
		/// <summary>
		/// Vector3's are structs brought in via interop.
		/// They have no accessors/properties, they have methods instead
		/// So GetProperties doesn't return anything and hence we declare
		/// here that properties are unsupported by returning false. 
		/// You can still use the ConvertFrom w/ strings to edit. 
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		public override bool GetPropertiesSupported(ITypeDescriptorContext context)
		{
			return false;
		}


		/// <summary>
		/// A test method to see what this converter can convert 
		/// from. Which for us is just string
		/// </summary>
		/// <param name="context"></param>
		/// <param name="sourceType">The Type that you want to convert from</param>
		/// <returns></returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			if( sourceType == typeof(string) )
				return true;
			return base.CanConvertFrom (context, sourceType);
		}

		/// <summary>
		/// A test method to see what this converter can convert to. For us
		/// this is Vector3
		/// </summary>
		/// <param name="context"></param>
		/// <param name="destinationType">The Type that you want to conver to</param>
		/// <returns></returns>
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			if( destinationType == typeof(Vector3) )
				return true;
			return base.CanConvertTo (context, destinationType);
		}

		/// <summary>
		/// Perform the actual conversion from string to vector3
		/// </summary>
		/// <param name="context"></param>
		/// <param name="culture"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
		{
			if( value is string)
			{
				string vectorString = (string) value;
				string[] floatStrings = Regex.Split(vectorString,"\\s*,\\s*");
				Vector3 vec = new Vector3(	float.Parse(floatStrings[0]),
					float.Parse(floatStrings[1]),
					float.Parse(floatStrings[2]));
				return vec;
			}
			return base.ConvertFrom (context, culture, value);
		}

		/// <summary>
		/// Perform the actual conversion from Vector3 to string
		/// </summary>
		/// <param name="context"></param>
		/// <param name="culture"></param>
		/// <param name="value"></param>
		/// <param name="destinationType"></param>
		/// <returns></returns>
		public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
		{
			if( destinationType == typeof(string) && value is Vector3 )
			{
				Vector3 v = (Vector3)value;
				return v.X.ToString("000.00") + " , " + v.Y.ToString("000.00") + " , " + v.Z.ToString("000.00");
			}
			return base.ConvertTo (context, culture, value, destinationType);
		}
	} // END D3DVector3TypeConverter


	/// <summary>
	/// Pull down menu in property grid for plant patch species
	/// </summary>
	public class PlantPatchSpeciesStringConverter : StringConverter 
	{
		/// <summary>
		/// TODO JERK
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		public override StandardValuesCollection
			GetStandardValues(ITypeDescriptorContext context) 
		{
			return new StandardValuesCollection(new string[]{"Poliferous Filoris", 
															 "Carniverous Grilled Cheeseeus", 
															 "Messesness Cleanusups",
															 "TODO JERK"});
		}
		/// <summary>
		/// todo jerk
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		public override bool GetStandardValuesSupported(
			ITypeDescriptorContext context) 
		{
			return true;
		}	
	} // END SpeciesConverter
}