using System;
using System.Collections.Generic;
using Server;
using Server.ContextMenus;
using Server.Engines.PartySystem;
using Server.Gumps;
using Server.Multis;
using Server.Network;

namespace Server.Items
{
	public class LootChest : LockableContainer
	{
		private int m_Level;
		private int m_Category;
		private DateTime m_ResetTime;
		private Mobile m_LastLooter;

		[CommandProperty( AccessLevel.GameMaster )]
		public int Level{ get{ return m_Level; } set{ m_Level = value; } }

		[CommandProperty( AccessLevel.GameMaster )]
		public int Category{ get{ return m_Category; } set{ m_Category = value; } }

		[CommandProperty( AccessLevel.GameMaster )]
		public Mobile LastLooter{ get{ return m_LastLooter; } set{ m_LastLooter = value; } }

		[CommandProperty( AccessLevel.GameMaster )]
		public DateTime ResetTime{ get{ return m_ResetTime; } }

		[Constructable]
		public LootChest() : base( 0xE40 )
		{
			m_ResetTime = DateTime.Now;
			Movable = false;
			m_Level = 1;
			m_Category = 1;

			/*			 Level 1				Level 2					Level 3					Thief 4
			------------+--------------------	---------------------	-------------------		---------------------	--------
			Type		|ID		ID		Hue		ID		ID		Hue		ID		ID		Hue		ID		ID		Hue		Category
			------------+--------------------	---------------------	-------------------		---------------------	--------
			Crate		|0xE3E	0xE3F	0		0xE3C	0xE3D	0		0x645	0x646	0		0x0E99	0x0E9A	0		1
			Wood Chest	|0x52D	0x52E	0x96D	0x5ED	0x5EE	0x96D	0xE42	0xE43	0		0x481	0x488	0		2
			Metal Chest	|0x9AB	0xE7C	0		0xE54	0xE55	0		0xE40	0xE41	0		0xE52	0xE53	0x4A5	3
			--------------------------------------------------------------------------------------------------------------------
			*/
		}

		public override void OnDoubleClick( Mobile from )
		{
			if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
			{
				if ( !(this is SunkenShip) )
					Setup();

				Fill( from );
				Open( from );
			}
			else
				from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
		}

		public override bool CheckLift( Mobile from, Item item, ref LRReason reject )
		{
			if ( m_Level > 3 )
			{
				int steal = m_Category * 33;
				if ( from.CheckSkill( SkillName.Stealing, (steal-38), (steal+11) ) )
				{
					from.SendMessage( "Your nimble fingers help you steal the item." );
					return base.CheckLift( from, item, ref reject );
				}
				else
				{
					from.SendMessage( "You try to steal the item, but you were not nimble enough so you lost it!" );
					item.Delete();
					return false;
				}
			}

			return base.CheckLift( from, item, ref reject );
		}

		public override bool OnDragDropInto( Mobile from, Item item, Point3D p )
		{
			if ( m_Level > 3 )
			{
				from.SendMessage( "You try to put the item in there, but somehow lose it!" );
				item.Delete();
				return false;
			}

			return base.OnDragDropInto( from, item, p );
		}

		public override bool TryDropItem( Mobile from, Item dropped, bool sendFullMessage )
		{
			if ( m_Level > 3 )
			{
				from.SendMessage( "You try to put the item in there, but somehow lose it!" );
				dropped.Delete();
				return false;
			}

			return base.TryDropItem( from, dropped, sendFullMessage );
		}

		public bool NeverLock()
		{
			if ( m_Category == 1 && m_Level < 4 )
				return true;

			return false;
		}

		public void Setup()
		{
			if ( DateTime.Now >= m_ResetTime )
			{
				m_ResetTime = DateTime.Now + TimeSpan.FromMinutes( ((double)(Utility.RandomMinMax(45,60))) );

				List<Item> o = new List<Item>();
				foreach( Item i in this.Items )
				{
					o.Add(i);
				}
				foreach ( Item g in o )
				{
					g.Delete();
				}

				Locked = false;
				TrapType = TrapType.None;
				TrapPower = 0;
				TrapLevel = 0;
				m_LastLooter = null;

				int i_Difficulty = ( m_Level * 18 ) + ( m_Category * 10 );

				if ( Utility.RandomMinMax(1,100) < i_Difficulty && !NeverLock() )
				{
					Locked = true;
					RequiredSkill = i_Difficulty;
					LockLevel = RequiredSkill - 10;
					MaxLockLevel = RequiredSkill + 30;
				}

				if ( Utility.RandomMinMax(1,100) < i_Difficulty )
				{
					switch ( Utility.Random( 4 ) )
					{
						case 0: TrapType = TrapType.MagicTrap; break;
						case 1: TrapType = TrapType.ExplosionTrap; break;
						case 2: TrapType = TrapType.DartTrap; break;
						case 3: TrapType = TrapType.PoisonTrap; break;
					}
					TrapPower = i_Difficulty;
					TrapLevel = 0;
				}
			}
		}

		public static int WepArmQuality( int level, int lvl, int cat )
		{
			if ( Utility.Random(8) < ( lvl + cat ) )
			{
				if ( level >= Utility.Random(1320) )
					return 6;
				else if ( level >= Utility.Random(1100) )
					return 5;
				else if ( level >= Utility.Random(880) )
					return 4;
				else if ( level >= Utility.Random(660) )
					return 3;
				else if ( level >= Utility.Random(440) )
					return 2;
			}

			return 1;
		}

		public static int PotionQuality( int level, int lvl, int cat )
		{
			if ( Utility.Random(8) < ( lvl + cat ) )
			{
				if ( level >= Utility.Random(660) )
					return 3;
				else if ( level >= Utility.Random(440) )
					return 2;
			}

			return 1;
		}

		public static int ScrollQuality( int level, int lvl, int cat )
		{
			int scroll = 24;

			if ( Utility.Random(8) < ( lvl + cat ) )
			{
				if ( level >= Utility.Random(800) )
					scroll = 64;
				else if ( level >= Utility.Random(400) )
					scroll = 56;
				else if ( level >= Utility.Random(200) )
					scroll = 48;
				else if ( level >= Utility.Random(100) )
					scroll = 40;
				else if ( level >= Utility.Random(50) )
					scroll = 32;
			}

			return scroll-1;
		}

		public Item TreasureItem( int level )
		{
			Item item = null;

			switch ( Utility.Random( 30 ) )
			{
				case 0: 
				case 1: 
					int pot = PotionQuality( level, m_Level, m_Category );
					switch ( Utility.Random( pot ) )
					{
						case 0: item = Loot.RandomLowPotion(); break;
						case 1: item = Loot.RandomMedPotion(); break;
						case 2: item = Loot.RandomHighPotion(); break;
					}
				break;
				case 2: 
				case 3: 
				case 4: item = Loot.RandomTool(); break;
				case 5: 
				case 6: 
				case 7: item = Loot.RandomMisc(); break;
				case 8: 
				case 9: 
				case 10: item = Loot.RandomCraft(); 
					if ( item is Cloth ){ item.Hue = Utility.RandomHue(); item.ItemID = Utility.RandomList( 0x1766, 0x1768 ); }
					else if ( item is BoltOfCloth ){ item.Hue = Utility.RandomHue(); item.ItemID = Utility.RandomList( 0xF95, 0xF96, 0xF97, 0xF98, 0xF99, 0xF9A, 0xF9B, 0xF9C ); }
				break;
				case 11: 
				case 12: 
				case 13: 
				case 14: 
				case 15: item = Loot.RandomProvisions(); break;
				case 16: 
				case 17: item = Loot.RandomGem(); break;
				case 18: 
				case 19: item = Loot.RandomReagent(); item.Amount = Utility.Random((int)(level/2))+5; break;
				case 20: item = Loot.RandomWand(); break;
				case 21: item = Loot.RandomClothing(); break;
				case 22: item = Loot.RandomRangedWeapon(); break;
				case 23: item = Loot.RandomWeapon(); break;
				case 24: item = Loot.RandomJewelry(); break;
				case 25: item = Loot.RandomArmor(); break;
				case 26: item = Loot.RandomShield(); break;
				case 27: item = Loot.RandomInstrument(); break;
				case 28:
				case 29: Loot.RandomScroll( 0, ScrollQuality( level, m_Level, m_Category ), SpellbookType.Regular ); break;
			}

			return item;
		}

		public void Fill( Mobile m )
		{
			if ( m_LastLooter == null )
			{
				int level = ( ( m_Level + m_Category ) * 10 ) + Server.SkillHandlers.Searching.TotalSearchSkill( m );
				int rank = m_Category + m_Level;

				/* *********** SEARCH SKILL PER TREASURE **********
				Box		None	Night	Light	Skill	Skill+Ns-Lt
				Lvl		-------------------------------------------
				Cat		0		25		50		100		125		150
				---------------------------------------------------
				2		20		45		70		120		145		170
				3		30		55		80		130		155		180
				4		40		65		90		140		165		190
				5		50		75		100		150		175		200
				6		60		85		110		160		185		210
				7		70		95		120		170		195		220
				---------------------------------------------------
				*/

				m_LastLooter = m;

				// --------------------------------------------------------------------------------

				int gold = level * Utility.RandomMinMax(5,10);
				double w = gold * (Server.Misc.Settings.GoldCutRate() * .01);
				gold = (int)w;
				DropItem( new Gold( gold ) );

				// --------------------------------------------------------------------------------

				if ( Utility.Random(2000) < level )
					DropItem( new TreasureMap( Utility.RandomMinMax(1,m_Level), Map.Britannia ) );

				// --------------------------------------------------------------------------------

				int numberItems = (int)( Utility.RandomMinMax( rank, ((level / 20)+rank) ) );
				
				for ( int i = 0; i < numberItems; ++i )
				{
					Item item = TreasureItem( level );

					if ( item != null )
					{
						MakeMagical( item, level, m_Level, m_Category );
						DropItem( item );
					}
				}
			}
		}

		public static void MakeMagical( Item item, int level, int lvl, int cat )
		{
			if ( item != null )
			{
				if ( item is BaseWeapon && !(item is BaseWand) )
				{
					BaseWeapon weapon = (BaseWeapon)item;

					weapon.DamageLevel = (WeaponDamageLevel)Utility.Random( WepArmQuality( level, lvl, cat ) );
					weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random( WepArmQuality( level, lvl, cat ) );
					weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random( WepArmQuality( level, lvl, cat ) );
				}
				else if ( item is BaseArmor )
				{
					BaseArmor armor = (BaseArmor)item;

					armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random( WepArmQuality( level, lvl, cat ) );
					armor.Durability = (ArmorDurabilityLevel)Utility.Random( WepArmQuality( level, lvl, cat ) );
				}
				else if ( item is BaseClothing )
				{
					BaseClothing cloth = (BaseClothing)item;
				}
			}
		}

		public LootChest( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int) 0 );
			writer.Write( m_LastLooter );
			writer.Write( (int) m_Level );
			writer.Write( (int) m_Category );
			writer.Write( m_ResetTime );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();

			m_LastLooter = reader.ReadMobile();
			m_Level = reader.ReadInt();
			m_Category = reader.ReadInt();
			m_ResetTime = reader.ReadDateTime();
		}
	}
}
