using System;
using System.Collections.Generic;
using Server.Items;
using Server.ContextMenus;
using Server.Misc;
using Server.Network;
using Server.Regions;

namespace Server.Mobiles
{
	public class Innkeeper : BaseVendor
	{
		private List<SBInfo> m_SBInfos = new List<SBInfo>();
		protected override List<SBInfo> SBInfos{ get { return m_SBInfos; } }

		[Constructable]
		public Innkeeper() : base( "the innkeeper" )
		{
			Item candle = new HeldLight();
			candle.Name = "candle";
			candle.ItemID = 0xA0F;
			candle.Light = LightType.Circle150;
			AddItem( candle );
		}

		public override void InitSBInfo()
		{
			m_SBInfos.Add( new SBInnKeeper() );
		}

		public static int GetBalance( Mobile from )
		{
			Item[] gold, checks;

			return GetBalance( from, out gold, out checks );
		}

		public static int GetBalance( Mobile from, out Item[] gold, out Item[] checks )
		{
			int balance = 0;

			Container inn = from.FindInnNoCreate();

			if ( inn != null )
			{
				gold = inn.FindItemsByType( typeof( Gold ) );
				checks = inn.FindItemsByType( typeof( GoldDeed ) );

				for ( int i = 0; i < gold.Length; ++i )
					balance += gold[i].Amount;

				for ( int i = 0; i < checks.Length; ++i )
					balance += ((GoldDeed)checks[i]).Worth;
			}
			else
			{
				gold = checks = new Item[0];
			}

			return balance;
		}

		public static bool Withdraw( Mobile from, int amount )
		{
			Item[] gold, checks;
			int balance = GetBalance( from, out gold, out checks );

			if ( balance < amount )
				return false;

			for ( int i = 0; amount > 0 && i < gold.Length; ++i )
			{
				if ( gold[i].Amount <= amount )
				{
					amount -= gold[i].Amount;
					gold[i].Delete();
				}
				else
				{
					gold[i].Amount -= amount;
					amount = 0;
				}
			}

			for ( int i = 0; amount > 0 && i < checks.Length; ++i )
			{
				GoldDeed check = (GoldDeed)checks[i];

				if ( check.Worth <= amount )
				{
					amount -= check.Worth;
					check.Delete();
				}
				else
				{
					check.Worth -= amount;
					amount = 0;
				}
			}

			return true;
		}

		public static bool Deposit( Mobile from, int amount )
		{
			InnBox box = from.FindInnNoCreate();
			if ( box == null )
				return false;

			List<Item> items = new List<Item>();

			while ( amount > 0 )
			{
				Item item;
				if ( amount < 5000 )
				{
					item = new Gold( amount );
					amount = 0;
				}
				else if ( amount <= 1000000 )
				{
					item = new GoldDeed( amount );
					amount = 0;
				}
				else
				{
					item = new GoldDeed( 1000000 );
					amount -= 1000000;
				}

				if ( box.TryDropItem( from, item, false ) )
				{
					items.Add( item );
				}
				else
				{
					item.Delete();
					foreach ( Item curItem in items )
					{
						curItem.Delete();
					}

					return false;
				}
			}

			return true;
		}

		public static int DepositUpTo( Mobile from, int amount )
		{
			InnBox box = from.FindInnNoCreate();
			if ( box == null )
				return 0;

			int amountLeft = amount;
			while ( amountLeft > 0 )
			{
				Item item;
				int amountGiven;

				if ( amountLeft < 5000 )
				{
					item = new Gold( amountLeft );
					amountGiven = amountLeft;
				}
				else if ( amountLeft <= 1000000 )
				{
					item = new GoldDeed( amountLeft );
					amountGiven = amountLeft;
				}
				else
				{
					item = new GoldDeed( 1000000 );
					amountGiven = 1000000;
				}

				if ( box.TryDropItem( from, item, false ) )
				{
					amountLeft -= amountGiven;
				}
				else
				{
					item.Delete();
					break;
				}
			}

			return amount - amountLeft;
		}

		public static void Deposit( Container cont, int amount )
		{
			while ( amount > 0 )
			{
				Item item;

				if ( amount < 5000 )
				{
					item = new Gold( amount );
					amount = 0;
				}
				else if ( amount <= 1000000 )
				{
					item = new GoldDeed( amount );
					amount = 0;
				}
				else
				{
					item = new GoldDeed( 1000000 );
					amount -= 1000000;
				}

				cont.DropItem( item );
			}
		}

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

		public override bool HandlesOnSpeech( Mobile from )
		{
			if ( from.InRange( this.Location, 12 ) )
				return true;

			return base.HandlesOnSpeech( from );
		}

		public override void OnSpeech( SpeechEventArgs e )
		{
			if ( !e.Handled && e.Mobile.InRange( this.Location, 12 ) && (e.Mobile).Region is InnRegion )
			{
				int keyword = 0;

				if ( e.Speech.ToLower().IndexOf( "withdraw" ) >= 0 ){ keyword = 1; }
				else if ( e.Speech.ToLower().IndexOf( "balance" ) >= 0 ){ keyword = 2; }
				else if ( e.Speech.ToLower().IndexOf( "inn" ) >= 0 ){ keyword = 3; }
				else if ( e.Speech.ToLower().IndexOf( "deed" ) >= 0 ){ keyword = 4; }

				switch ( keyword )
				{
					case 1: // *withdraw*
					{
						e.Handled = true;

						if ( e.Mobile.Criminal )
						{
							this.Say( 500389 ); // I will not do business with a criminal!
							break;
						}

						string[] split = e.Speech.Split( ' ' );

						if ( split.Length >= 2 )
						{
							int amount;

							Container pack = e.Mobile.Backpack;

							if ( !int.TryParse( split[1], out amount ) )
								break;

							if ( amount > 5000 )
							{
								this.Say( 500381 ); // Thou canst not withdraw so much at one time!
							}
							else if (pack == null || pack.Deleted || !(pack.TotalWeight < pack.MaxWeight) || !(pack.TotalItems < pack.MaxItems))
							{
								this.Say(1048147); // Your backpack can't hold anything else.
							}
							else if (amount > 0)
							{
								InnBox box = e.Mobile.FindInnNoCreate();

								if (box == null || !box.ConsumeTotal(typeof(Gold), amount))
								{
									this.Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold!
								}
								else
								{
									pack.DropItem(new Gold(amount));

									this.Say(1010005); // Thou hast withdrawn gold from thy account.
								}
							}
						}

						break;
					}
					case 2: // *balance*
					{
						e.Handled = true;

						if ( e.Mobile.Criminal )
						{
							this.Say( 500389 ); // I will not do business with a criminal!
							break;
						}

						InnBox box = e.Mobile.FindInnNoCreate();

						if ( box != null )
							this.Say( 1042759, box.TotalGold.ToString() ); // Thy current inn balance is ~1_AMOUNT~ gold.
						else
							this.Say( 1042759, "0" ); // Thy current inn balance is ~1_AMOUNT~ gold.

						break;
					}
					case 3: // *inn*
					{
						e.Handled = true;

						if ( e.Mobile.Criminal )
						{
							this.Say( 500378 ); // Thou art a criminal and cannot access thy inn chest.
							break;
						}

						e.Mobile.InnBox.Open();

						break;
					}
					case 4: // *deed*
					{
						e.Handled = true;

						if ( e.Mobile.Criminal )
						{
							this.Say( 500389 ); // I will not do business with a criminal!
							break;
						}

						string[] split = e.Speech.Split( ' ' );

						if ( split.Length >= 2 )
						{
							int amount;

							if ( !int.TryParse( split[1], out amount ) )
								break;

							if ( amount < 5000 )
							{
								this.Say( 1010006 ); // We cannot create gold deeds for such a paltry amount of gold!
							}
							else if ( amount > 1000000 )
							{
								this.Say( 1010007 ); // Our policies prevent us from creating gold deeds worth that much!
							}
							else
							{
								GoldDeed check = new GoldDeed( amount );

								InnBox box = e.Mobile.InnBox;

								if ( !box.TryDropItem( e.Mobile, check, false ) )
								{
									this.Say( 500386 ); // There's not enough room in your inn chest for the gold deed!
									check.Delete();
								}
								else if ( !box.ConsumeTotal( typeof( Gold ), amount ) )
								{
									this.Say( 500384 ); // Ah, art thou trying to fool me? Thou hast not so much gold!
									check.Delete();
								}
								else
								{
									this.Say( 1042673, AffixType.Append, amount.ToString(), "" ); // Into your inn chest I have placed a gold deed in the amount of:
								}
							}
						}

						break;
					}
				}
			}

			base.OnSpeech( e );
		}

		public override void AddCustomContextEntries( Mobile from, List<ContextMenuEntry> list )
		{
			if ( from.Alive )
				list.Add( new OpenInnEntry( from, this ) );

			base.AddCustomContextEntries( from, list );
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 0 ); // version
		}

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

			int version = reader.ReadInt();
		}
	}
}

namespace Server.Items
{
	public class HeldLight : BaseEquipableLight
	{
		public override int LitItemID{ get { return 0xA22; } }
		public override int UnlitItemID{ get { return 0xA22; } }

		[Constructable]
		public HeldLight() : base( 0xA22 )
		{
			Name = "lantern";
			Duration = TimeSpan.Zero;
			Burning = true;
			Light = LightType.Circle300;
			Weight = 2.0;
			LootType = LootType.Blessed;

			switch ( Utility.Random( 3 ) )
			{
				default:
				case 0: Name = "torch";		ItemID = 0xA12;		Light = LightType.Circle300;	break;
				case 1: Name = "candle";	ItemID = 0xA0F;		Light = LightType.Circle150;	break;
			}
		}

		public override bool DisplayLootType{ get{ return false; } }

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

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

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();
		}
	}
}