using System;
using System.Collections;

namespace Server.Engines.Plants
{
	[Flags]
	public enum PlantHue
	{
		Plain			= 0x1 | Crossable,

		Red				= 0x2 | Crossable,
		Blue			= 0x4 | Crossable,
		Yellow			= 0x8 | Crossable,

		BrightRed		= Red | Bright,
		BrightBlue		= Blue | Bright,
		BrightYellow	= Yellow | Bright,

		Purple			= Red | Blue,
		Green			= Blue | Yellow,
		Orange			= Red | Yellow,

		BrightPurple	= Purple | Bright,
		BrightGreen		= Green | Bright,
		BrightOrange	= Orange | Bright,

		Black			= 0x10,
		White			= 0x20,
		Pink			= 0x40,
		Magenta			= 0x80,
		Aqua			= 0x100,
		FireRed			= 0x200,

		None			= 0,
		Crossable		= 0x4000000,
		Bright			= 0x8000000
	}

	public class PlantHueInfo
	{
		private static readonly Hashtable m_Table;

		static PlantHueInfo()
		{
			m_Table = new Hashtable();

			m_Table[PlantHue.Plain]			= new PlantHueInfo( 0,		1060813, PlantHue.Plain,		0x835 );
			m_Table[PlantHue.Red]			= new PlantHueInfo( 0x66D,	1060814, PlantHue.Red,			0x24 );
			m_Table[PlantHue.Blue]			= new PlantHueInfo( 0x53D,	1060815, PlantHue.Blue,			0x6 );
			m_Table[PlantHue.Yellow]		= new PlantHueInfo( 0x8A5,	1060818, PlantHue.Yellow,		0x38 );
			m_Table[PlantHue.BrightRed]		= new PlantHueInfo( 0x21,	1060814, PlantHue.BrightRed,	0x21 );
			m_Table[PlantHue.BrightBlue]	= new PlantHueInfo( 0x5,	1060815, PlantHue.BrightBlue,	0x6 );
			m_Table[PlantHue.BrightYellow]	= new PlantHueInfo( 0x38,	1060818, PlantHue.BrightYellow,	0x35 );
			m_Table[PlantHue.Purple]		= new PlantHueInfo( 0xD,	1060816, PlantHue.Purple,		0x10 );
			m_Table[PlantHue.Green]			= new PlantHueInfo( 0x59B,	1060819, PlantHue.Green,		0x42 );
			m_Table[PlantHue.Orange]		= new PlantHueInfo( 0x46F,	1060817, PlantHue.Orange,		0x2E );
			m_Table[PlantHue.BrightPurple]	= new PlantHueInfo( 0x10,	1060816, PlantHue.BrightPurple,	0xD );
			m_Table[PlantHue.BrightGreen]	= new PlantHueInfo( 0x42,	1060819, PlantHue.BrightGreen,	0x3F );
			m_Table[PlantHue.BrightOrange]	= new PlantHueInfo( 0x2B,	1060817, PlantHue.BrightOrange,	0x2B );
			m_Table[PlantHue.Black]			= new PlantHueInfo( 0x455,	1060820, PlantHue.Black,		0 );
			m_Table[PlantHue.White]			= new PlantHueInfo( 0x481,	1060821, PlantHue.White,		0x481 );
			m_Table[PlantHue.Pink]			= new PlantHueInfo( 0x9C0,	1061854, PlantHue.Pink );
			m_Table[PlantHue.Magenta]		= new PlantHueInfo( 0xAEC,	1061852, PlantHue.Magenta );
			m_Table[PlantHue.Aqua]			= new PlantHueInfo( 0x79B,	1061853, PlantHue.Aqua );
			m_Table[PlantHue.FireRed]		= new PlantHueInfo( 0x9D7,	1061855, PlantHue.FireRed );
		}

		public static PlantHueInfo GetInfo( PlantHue plantHue )
		{
			PlantHueInfo info = m_Table[plantHue] as PlantHueInfo;

			if ( info != null )
				return info;
			else
				return (PlantHueInfo)m_Table[PlantHue.Plain];
		}

		public static PlantHue RandomFirstGeneration()
		{
			switch ( Utility.Random( 4 ) )
			{
				case 0: return PlantHue.Plain;
				case 1: return PlantHue.Red;
				case 2: return PlantHue.Blue;
				default: return PlantHue.Yellow;
			}
		}

		public static bool IsCrossable( PlantHue plantHue )
		{
			return (plantHue & PlantHue.Crossable) != PlantHue.None;
		}

		public static bool IsBright( PlantHue plantHue )
		{
			return (plantHue & PlantHue.Bright) != PlantHue.None;
		}

		public static PlantHue GetNotBright( PlantHue plantHue )
		{
			return plantHue & ~PlantHue.Bright;
		}

		public static bool IsPrimary( PlantHue plantHue )
		{
			return plantHue == PlantHue.Red || plantHue == PlantHue.Blue || plantHue == PlantHue.Yellow;
		}

		public static PlantHue Cross( PlantHue first, PlantHue second )
		{
			if ( !IsCrossable( first ) || !IsCrossable( second ) )
				return PlantHue.None;

			if ( Utility.RandomDouble() < 0.01 )
				return Utility.RandomBool() ? PlantHue.Black : PlantHue.White;

			if ( first == PlantHue.Plain || second == PlantHue.Plain )
				return PlantHue.Plain;

			PlantHue notBrightFirst = GetNotBright( first );
			PlantHue notBrightSecond = GetNotBright( second );

			if ( notBrightFirst == notBrightSecond )
				return first | PlantHue.Bright;

			bool firstPrimary = IsPrimary( notBrightFirst );
			bool secondPrimary = IsPrimary( notBrightSecond );

			if ( firstPrimary && secondPrimary )
				return notBrightFirst | notBrightSecond;

			if ( firstPrimary && !secondPrimary )
				return notBrightFirst;

			if ( !firstPrimary && secondPrimary )
				return notBrightSecond;

			return notBrightFirst & notBrightSecond;
		}

		private readonly int m_Hue;
		private readonly int m_Name;
		private readonly PlantHue m_PlantHue;
		private readonly int m_GumpHue;

		public int Hue { get { return m_Hue; } }
		public int Name { get { return m_Name; } }
		public PlantHue PlantHue { get { return m_PlantHue; } }
		public int GumpHue { get { return m_GumpHue; } }

		private PlantHueInfo( int hue, int name, PlantHue plantHue ) : this( hue, name, plantHue, hue )
		{
		}

		private PlantHueInfo( int hue, int name, PlantHue plantHue, int gumpHue )
		{
			m_Hue = hue;
			m_Name = name;
			m_PlantHue = plantHue;
			m_GumpHue = gumpHue;
		}

		public bool IsCrossable()
		{
			return IsCrossable( m_PlantHue );
		}

		public bool IsBright()
		{
			return IsBright( m_PlantHue );
		}

		public PlantHue GetNotBright()
		{
			return GetNotBright( m_PlantHue );
		}

		public bool IsPrimary()
		{
			return IsPrimary( m_PlantHue );
		}
	}
}