// 11-22-06

using System;
using System.Collections.Generic;
using Server;
using Server.Items;
using Server.ContextMenus;
using Server.Engines.Craft;

namespace Server.Items
{
	public enum QuiverQuality
	{
		Low,
		Regular,
		Exceptional
	}

	public class Quiver : BaseContainer, ICraftable
	{
		public static int GlobalReduced = 25;
		public static Layer QuiverLayer = Layer.Cloak;

		private QuiverQuality p_Quality = QuiverQuality.Regular;

		[CommandProperty( AccessLevel.GameMaster )]
		public QuiverQuality Quality{ get{ return p_Quality; } set{ p_Quality = value; ScaleAttribs(); InvalidateProperties(); }}

		private int p_ReducedOffset = 0;

		[CommandProperty( AccessLevel.GameMaster )]
		public int ReducedOffset{ get{ return p_ReducedOffset; } set{ p_ReducedOffset = value; ScaleWeight(); InvalidateProperties(); }}

		public virtual double Reduced{ get{ return GlobalReduced + p_ReducedOffset; }}

		private int p_Arrows, p_Bolts, p_Bonus;

		[CommandProperty( AccessLevel.GameMaster )]
		public int Arrows{ get{ return p_Arrows; } set{ p_Arrows = value; ScaleWeight(); InvalidateProperties(); } }
		[CommandProperty( AccessLevel.GameMaster )]
		public int Bolts{ get{ return p_Bolts; } set{ p_Bolts = value; ScaleWeight(); InvalidateProperties(); } }
		[CommandProperty( AccessLevel.GameMaster )]
		public int Bonus{ get{ return p_Bonus; } set{ p_Bonus = value; InvalidateProperties(); } }

		public virtual int Contained{ get{ return p_Arrows + p_Bolts; }}
		public virtual int MaxContained{ get{ return 100 + p_Bonus; }}

		private int p_LowerAmmoCost;
		private AosAttributes p_AosAttributes;
		private AosSkillBonuses p_AosSkillBonuses;
		private Mobile p_Crafter;

		[CommandProperty( AccessLevel.GameMaster )]
		public int LowerAmmoCost { get{ return p_LowerAmmoCost; } set{ p_LowerAmmoCost = value; InvalidateProperties(); } }
		[CommandProperty( AccessLevel.GameMaster )]
		public AosAttributes Attributes	{ get{ return p_AosAttributes; } set{} }
		[CommandProperty( AccessLevel.GameMaster )]
		public AosSkillBonuses SkillBonuses	{ get{ return p_AosSkillBonuses; } set{} }
		[CommandProperty( AccessLevel.GameMaster )]
		public Mobile Crafter {	get{ return p_Crafter; } set{ p_Crafter = value; InvalidateProperties(); } }
		
		[Constructable]
		public Quiver() : base( 0x2B03 )
		{
			Name = "a quiver";
			Weight = 2.0;
			Layer = QuiverLayer;
			p_AosAttributes = new AosAttributes( this );
			p_AosSkillBonuses = new AosSkillBonuses( this );
		}

		public static bool Consume( Type type, Quiver q )
		{
			if( q == null )
				return false;

			if( type == typeof( Arrow ) )
			{
				if( q.Arrows > 0 )
				{
					--q.Arrows;
					return true;
				}
			}
			else
			{
				if( q.Bolts > 0 )
				{
					--q.Bolts;
					return true;
				}
			}

			return false;
		}

		public override void GetProperties( ObjectPropertyList list )
		{
			base.GetProperties( list );
			p_AosSkillBonuses.GetProperties( list );
			int prop;
			
			if ( p_Crafter != null )
				list.Add( 1050043, p_Crafter.Name ); // crafted by ~1_NAME~

			if ( p_Quality == QuiverQuality.Exceptional )
				list.Add( 1060636 ); // exceptional

			list.Add( 1060658, String.Format( "{0}Arrows\t{1}", ( (p_Crafter != null || this.Quality == QuiverQuality.Exceptional) ? "<br>" : ""), Arrows.ToString() ));
			
			list.Add( 1060659, String.Format( "Bolts\t{0}", Bolts.ToString() ));
			
			list.Add( 1060660, String.Format( "Holds\t{0} Arrows/Bolts<br>", MaxContained ));

			if ( (prop = p_AosAttributes.DefendChance) != 0 )
				list.Add( 1060408, prop.ToString() ); //Defend Chance ~1_val~%
			
			if ( (prop = p_AosAttributes.WeaponDamage) != 0 )
				list.Add( 1060401, prop.ToString() ); //Weapon Damage ~1_val~
			
			if ( (prop = LowerAmmoCost) != 0 )
				list.Add( 1075208, prop.ToString() ); //Lower Ammo Cost ~1_PERCENTAGE~%
			
			if( this.Reduced > 0 )
				list.Add( 1072210, this.Reduced.ToString() ); //Weight reduction ~1_PERCENTAGE~%

			list.Add( 1072788 + (Math.Ceiling((double)Weight) > 1 ? 1 : 0), Math.Ceiling((double)Weight).ToString() ); //Weight: ~1_WEIGHT~ stone || Weight: ~1_WEIGHT~ stones
		}

		public override bool OnDragDrop( Mobile from, Item target )
		{
			if( target is Arrow || target is Bolt )
			{
				if( this.Contained < this.MaxContained )
				{
					int amt = target.Amount;
					if( this.Contained + amt > this.MaxContained )
						amt = this.MaxContained - this.Contained;

					bool arrow = false;
					if( target is Arrow )
						arrow = true;

					from.SendMessage( "You put {0} {1}{2} into your quiver.", amt, ( arrow ? "arrow" : "bolt" ), ( (amt > 1) ? "s" : "" ) );
					if( arrow )
						this.p_Arrows += amt;
					else
						this.p_Bolts += amt;

					if( amt < target.Amount )
						target.Amount -= amt;
					else
						target.Delete();

					ScaleWeight();
				}
				else
					from.SendMessage( "That cannot hold any more items!" );
			}

			return base.OnDragDrop( from, target );
		}

		public int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue )
		{
			Quality = (QuiverQuality)quality;

			if ( makersMark )
				Crafter = from;

			ScaleAttribs();

			return quality;
		}

		public void ScaleWeight()
		{
			double arrows = this.Arrows * 0.1;//(Arrow.DefaultWeight);
			double bolts = this.Bolts * 0.1;//(Bolt.DefaultWeight);
			double tomult = 1.0 - ((double)this.Reduced / 100);

			this.Weight = 1.0 + Math.Ceiling((double)(arrows + bolts) * tomult);
		}

		public void ScaleAttribs()
		{
			if( Quality == QuiverQuality.Regular )
			{
				ReducedOffset = 5 + (Utility.Random(5)*5); // Min: 5, Max: 25
				Bonus = (Utility.Random( 10 )*20) + 100; // Min: 10, Max: 50
				LowerAmmoCost = (Utility.Random( 5 )*5) + 10; // Min: 10, Max: 35
			}
			else if( Quality == QuiverQuality.Exceptional )
			{
				ReducedOffset = 25 + (Utility.Random(8)*5); // Min: 25, Max: 65
				Bonus = (Utility.Random( 20 )*20) + 200; // Min: 10, Max: 100
				LowerAmmoCost = (Utility.Random( 10 )*5) + 25; // Min: 25, Max: 75
			}
			else
			{
				ReducedOffset = (5 + (Utility.Random(2)*5)) * -1; // Min: -5, Max: -10
				Bonus = (5 + (Utility.Random( 5 )*5)) * -1; // Min: -5, Max: -25
				LowerAmmoCost = 0; // 0
			}
		}

		public override bool OnEquip( Mobile from )
		{
			p_AosSkillBonuses.AddTo( from );
			return base.OnEquip( from );
		}

		public override void OnRemoved( object parent )
		{
			p_AosSkillBonuses.Remove();
			base.OnRemoved( parent );
		}

		public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
		{
			if( from.CanSee( this ) && from.InRange( this.GetWorldLocation(), 2 ) && from.InLOS( this ) && this.IsAccessibleTo( from ) && (this.Arrows > 0 || this.Bolts > 0 ))
				list.Add( new TransferEntry( from, this ) );
		}

		private class TransferEntry : ContextMenuEntry
		{
			private Mobile Mob;
			private Quiver Item;

			public TransferEntry( Mobile from, Item item ) : base( 0512 ) // uses "Transfer" entry
			{
				Item = (Quiver)item;
				Mob = from;
			}

			public override void OnClick()
			{
				if( Item.Arrows <= 0 && Item.Bolts <= 0 )
					return;

				Arrow arrow = null;
				Bolt bolt = null;
				if( Item.Arrows > 0 )
					arrow = new Arrow( Item.Arrows );
				if( Item.Bolts > 0 )
					bolt = new Bolt( Item.Bolts );

				if( arrow != null )
				{
					if( !Mob.Backpack.TryDropItem( Mob, arrow, true ) )
						arrow.MoveToWorld( Mob.Location, Mob.Map );
				}
				if( bolt != null )
				{
					if( !Mob.Backpack.TryDropItem( Mob, bolt, true ) )
						bolt.MoveToWorld( Mob.Location, Mob.Map );
				}

				if( Item.Arrows > 0 && Item.Bolts <= 0 )
					Mob.SendMessage( "You take {0} arrow{1} out of your quiver.", Item.Arrows, ( (Item.Arrows > 0) ? "s" : "" ) );
				else if( Item.Arrows <= 0 && Item.Bolts > 0 )
					Mob.SendMessage( "You take {0} bolt{1} out of your quiver.", Item.Bolts, ( (Item.Bolts > 0) ? "s" : "" ) );
				else
					Mob.SendMessage( "You take {0} arrow{1} and {2} bolt{3} out of your quiver.", Item.Arrows, ( (Item.Arrows > 0) ? "s" : "" ), Item.Bolts, ( (Item.Bolts > 0) ? "s" : "" ) );

				Item.Arrows = 0;
				Item.Bolts = 0;
			}
		}


		public Quiver( Serial serial ) : base( serial )
		{
		}
		
		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int) 0 ); // version
			
			writer.Write( (int)Quality );
			
			writer.Write( p_ReducedOffset );

			writer.Write( p_Arrows );
			writer.Write( p_Bolts );
			writer.Write( p_Bonus );

			writer.Write( (int) p_LowerAmmoCost );
			p_AosAttributes.Serialize( writer );
			p_AosSkillBonuses.Serialize( writer );
			writer.Write( p_Crafter );
		}
		
		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();
			
			switch ( version )
			{
				case 0:
				{
					p_Quality = (QuiverQuality)reader.ReadInt();

					p_ReducedOffset = reader.ReadInt();

					p_Arrows = reader.ReadInt();
					p_Bolts = reader.ReadInt();
					p_Bonus = reader.ReadInt();

					p_LowerAmmoCost = reader.ReadInt();
					p_AosAttributes = new AosAttributes( this, reader );
					p_AosSkillBonuses = new AosSkillBonuses( this, reader );
					p_Crafter = reader.ReadMobile();
					break;
				}
			}
		}
	}
}
