/**********************************************************
RunUO 2.0 AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by 
Filepath: scripts\_custom\items\potions\Conflagaration\BaseConflagarationPotion.cs
Lines of code: 228
***********************************************************/


using System;
using System.Collections;
using Server;
using Server.Network;
using Server.Targeting;
using Server.Spells;
using Server.Misc;
using Server.Items;

namespace Server.Items
{
	public abstract class BaseConflagarationPotion : BasePotion
	{
		public abstract int MinDamage { get; }
		public abstract int MaxDamage { get; }

		public override bool RequireFreeHand{ get{ return false; } }
		
		public override bool CanBeTriggered{get{return true;} }
		public abstract int ExplosionRange { get; }
		


		public BaseConflagarationPotion( PotionEffect effect ) : base( 3846, effect )
		{
			Hue = 1161;
		}

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

		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();
		}


		public override void Drink( Mobile from )
		{
			if ( Core.AOS && (from.Paralyzed || from.Frozen || (from.Spell != null && from.Spell.IsCasting)))
			{
				from.SendMessage( "You cannot use this at this moment" );
				return;
			}
			else if(UseDelaySystem.CheckContext(from, DelayContextType.ConflagPotion))
			{
				from.SendMessage("You must wait 20 seconds between conflagaration potions");
				return;	
			}

			
			ThrowTarget targ = from.Target as ThrowTarget;

			if ( targ != null && targ.Potion == this )
				return;			
			
			
			if(!IsChildOf( from.Backpack ))
			{
				Explode( from, true, Location, Map );
			}
			else
			{				
				from.SendMessage("Target a location to throw the potion");
				from.Target = new ThrowTarget( this,from );
			}

			from.RevealingAction();
		}
		
		
		
		public override bool OnTrigger(Mobile from,Item itemfrom,TriggerType type)
		{
			if(0.1>Utility.RandomDouble())return false;
			
			bool dotrigger=false;
			if(type==TriggerType.Explosion)dotrigger=true;
			else if(type==TriggerType.Impact && 0.2>Utility.RandomDouble())dotrigger=true;
			else if(type==TriggerType.Heat && 0.4>Utility.RandomDouble())dotrigger=true;
			
			if(dotrigger)Explode( from, false, this.Location,this.Map );
			
			return dotrigger;
		}		
		
		
		

		private void Reposition_OnTick( object state )
		{
			if ( Deleted )
				return;

			object[] states = (object[])state;
			Mobile from = (Mobile)states[0];
			IPoint3D p = (IPoint3D)states[1];
			Map map = (Map)states[2];

			Point3D loc = new Point3D( p );
			

			Explode( from, true, loc, map );
		}

		public class ThrowTarget : Target
		{
			private BaseConflagarationPotion m_Potion;

			public BaseConflagarationPotion Potion
			{
				get{ return m_Potion; }
			}

			public ThrowTarget( BaseConflagarationPotion potion,Mobile from ) : base( 12, true, TargetFlags.None )
			{
				m_Potion = potion;
			
				if(potion.Amount>1)
				{
					Type t = potion.GetType();
					
					Item newstack = Activator.CreateInstance(t) as Item;
					newstack.Amount=potion.Amount-1;
					m_Potion.Amount=1;
					m_Potion.Stackable=false; //so new stack wont just get readded to it, this particular pot is going to blow anyway
					
					if(!potion.IsChildOf( from.Backpack ))newstack.MoveToWorld(from.Location,from.Map);
					else if(from.Backpack!=null)
					{
						Container pack = from.Backpack;
						pack.AddItem(newstack);					
					}
					newstack.X=m_Potion.X;
					newstack.Y=m_Potion.Y;					
				}			
			}

			protected override void OnTarget( Mobile from, object targeted )
			{
				if ( m_Potion.Deleted || m_Potion.Map == Map.Internal )
					return;

				IPoint3D p = targeted as IPoint3D;

				if ( p == null )
					return;

				Map map = from.Map;

				if ( map == null )
					return;
								
				UseDelaySystem.AddContext(from, DelayContextType.ConflagPotion, TimeSpan.FromSeconds(20));

				SpellHelper.GetSurfaceTop( ref p );

				from.RevealingAction();

				IEntity to;

				if ( p is Mobile )
					to = (Mobile)p;
				else
					to = new Entity( Serial.Zero, new Point3D( p ), map );
					

				UseDelaySystem.AddContext(from, DelayContextType.ConflagPotion, TimeSpan.FromSeconds(20));

				Effects.SendMovingEffect( from, to, m_Potion.ItemID & 0x3FFF, 7, 0, false, false, m_Potion.Hue, 0 );

				//m_Potion.Internalize();
				Timer.DelayCall( TimeSpan.FromSeconds( 0.7 ), new TimerStateCallback( m_Potion.Reposition_OnTick ), new object[]{ from, p, map } );
			}
			
			protected override void OnTargetCancel( Mobile from, TargetCancelType cancelType )
			{
				UseDelaySystem.RemoveContext(from,DelayContextType.ConflagPotion);
			}			
		}

		public void Explode( Mobile from, bool direct, Point3D loc, Map map )
		{
			if ( Deleted )
				return;
			
			int duration = 15;
			int damage=MinDamage + Utility.Random(MaxDamage-MinDamage);
			
			duration+=Amount/10;
			
			int range=ExplosionRange;
			
			for(int i=0;i<=range*2;i++)
			{
				for(int ii=0;ii<=range*2;ii++)
				{
					if(0.2>Utility.RandomDouble())new InternalItem( Utility.RandomBool() ? 0x398C : 0x3996, new Point3D(loc.X-range+i,loc.Y-range+ii,loc.Z), map,TimeSpan.FromSeconds(duration), 0 );
				}
			}
						
			wildfirecenter core = new wildfirecenter(duration,range,damage,from);
			core.MoveToWorld(loc,map);

			Effects.PlaySound( loc, map, 0x5CF );
			Delete();			
		}
	}
}

		public class InternalItem : Item
		{
			private Timer m_Timer;
			private DateTime m_End;

			
			public override bool BlocksFit{ get{ return true; } }

            public InternalItem( int itemID, Point3D loc,Map map, TimeSpan duration, int val ) : base( itemID )
			{
                bool canFit = SpellHelper.AdjustField( ref loc, map, 12, false );

				Visible = false;
				Movable = false;
				Light = LightType.Circle300;

				MoveToWorld( loc, map );

				
				m_End = DateTime.Now + duration;

				m_Timer = new InternalTimer( this, TimeSpan.FromSeconds( Math.Abs( val ) * 0.2 ), canFit );
				m_Timer.Start();
			}

			public override void OnAfterDelete()
			{
				base.OnAfterDelete();

				if ( m_Timer != null )
					m_Timer.Stop();
			}

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

			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();
				
				this.Delete();
			}


			private class InternalTimer : Timer
			{
				private InternalItem m_Item;
				private bool m_CanFit;

				private static Queue m_Queue = new Queue();

				public InternalTimer( InternalItem item, TimeSpan delay,bool canFit ) : base( delay, TimeSpan.FromSeconds( 1.0 ) )
				{
					m_Item = item;
					m_CanFit = canFit;

					Priority = TimerPriority.FiftyMS;
				}

				protected override void OnTick()
				{
					if ( m_Item.Deleted )
						return;

					if ( !m_Item.Visible )
					{
						if ( m_CanFit )
							m_Item.Visible = true;
						else
							m_Item.Delete();

						if ( !m_Item.Deleted )
						{
							m_Item.ProcessDelta();
							Effects.SendLocationParticles( EffectItem.Create( m_Item.Location, m_Item.Map, EffectItem.DefaultDuration ), 0x376A, 9, 10, 5029 );
						}
					}
					else if ( DateTime.Now > m_Item.m_End )
					{
						m_Item.Delete();
						Stop();
					}

				}
			}
		}