using System;
using Server;
using Server.Targeting;
using Server.Items;
using Server.Network;
using Server.Mobiles;
using System.Collections;
using System.Collections.Generic;

namespace Server.Spells.Sixth
{
	public class ExplosionSpell : Spell
	{
		private static SpellInfo m_Info = new SpellInfo(
				"Explosion", "Vas Ort Flam",
				SpellCircle.Sixth,
				230,
				9041,
				Reagent.Bloodmoss,
				Reagent.MandrakeRoot
			);

		public ExplosionSpell(Mobile caster, Item scroll)
		: base(caster, scroll, m_Info)
		{
		}

		public override bool DelayedDamageStacking { get { return !Core.AOS; } }

		public override void OnCast()
		{
			Caster.Target = new InternalTarget(this);
		}

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

		public void Target(Mobile m)
		{
			if (!Caster.CanSee(m))
			{
				Caster.SendLocalizedMessage(500237); // Target can not be seen.
			}
			else if (Caster.CanBeHarmful(m) && CheckSequence())
			{
				Mobile attacker = Caster, defender = m;

				SpellHelper.Turn(Caster, m);

				SpellHelper.CheckReflect((int) this.Circle, Caster, ref m);

				InternalTimer t = new InternalTimer(this, attacker, defender, m);
				t.Start();
			}

			FinishSequence();
		}

		private class InternalTimer : Timer
		{
			private Spell m_Spell;
			private Mobile m_Target;
			private Mobile m_Attacker, m_Defender;

			public InternalTimer(Spell spell, Mobile attacker, Mobile defender, Mobile target)
			: base(TimeSpan.FromSeconds(Core.AOS ? 3.0 : 2.5))
			{
				m_Spell = spell;
				m_Attacker = attacker;
				m_Defender = defender;
				m_Target = target;

				if (m_Spell != null)
					m_Spell.StartDelayedDamageContext(attacker, this);

				Priority = TimerPriority.FiftyMS;
			}

			protected override void OnTick()
			{
				if (m_Attacker.HarmfulCheck(m_Defender))
				{
					double damage;

					if (m_Defender.Map != Map.Underworld)
					{
						damage = m_Spell.GetNewAosDamage(40, 1, 5, m_Defender);
					}
					else
					{
						damage = Utility.Random(23, 22);

						if (m_Spell.CheckResisted(m_Target))
						{
							damage *= 0.75;

							m_Target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
						}

						damage *= m_Spell.GetDamageScalar(m_Target);
					}

					m_Target.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
					m_Target.PlaySound(0x307);

					//Corpse explosion
					if (m_Attacker.Player && m_Defender.Map != Map.Underworld && m_Attacker.Backpack != null && m_Target != null && !m_Target.Deleted && m_Target.Alive && m_Target != m_Attacker)
					{
						BaseCharm charm = (BaseCharm)m_Attacker.Backpack.FindItemByType(typeof(CharmOfCorpseExplosion));

						if (charm != null && charm.Charges > 0 && charm.BlessedFor == m_Attacker)
						{
							int count = 0;

							//                      if ( charm.Charges < 100000000 )
							//                         m_Attacker.SendMessage( "{0} charges: {1}", charm.Name, charm.Charges );

							foreach (Item item in m_Target.GetItemsInRange(2))
							{
								if (item is Corpse)
								{
									Corpse corpse = (Corpse) item;

									if (corpse.Carved || corpse.Channeled || corpse.Owner is PlayerMobile)
										continue;
									else
									{
										Timer.DelayCall(TimeSpan.FromMilliseconds(Utility.RandomMinMax(500, 2000)), new TimerStateCallback(ExplodeNearbyCorpse), new object[] { corpse, charm });
										count++;

										if (count > 2)
											break;
									}
								}
							}
						}
					}

					SpellHelper.Damage(m_Spell, m_Target, damage, 0, 100, 0, 0, 0);

					if (m_Spell != null)
						m_Spell.RemoveDelayedDamageContext(m_Attacker);
				}
			}

			private void ExplodeNearbyCorpse(object state)
			{
				object[] args = (object[])state;
				Corpse corpse = (Corpse) args[0];
				BaseCharm charm = (BaseCharm) args[1];

				if (charm == null || corpse == null || corpse.Deleted || corpse.Owner == null || m_Target == null || m_Target.Deleted || !m_Target.Alive || m_Attacker == null)
					return;
				else
				{
					AOS.Damage(m_Target, m_Attacker, AOS.Scale(corpse.Owner.HitsMax, Utility.RandomMinMax(15, 30)), 30, 70, 0, 0, 0, 1);

					Effects.SendLocationParticles(EffectItem.Create(corpse.Location, corpse.Map, EffectItem.DefaultDuration), 14000, 9, 32, 5024);
					Effects.PlaySound(corpse.Location, corpse.Map, Utility.RandomList(0x309, 0x208, 0x307));

					corpse.Channeled = true;
					corpse.ProcessDelta();
					corpse.SendRemovePacket();
					corpse.ItemID = Utility.Random(0xECA, 9); // bone graphic
			      corpse.Hue = 2544;
					corpse.ProcessDelta();

					if (charm.Charges > 1)
						charm.Charges--;
				}
			}
		}

		private class InternalTarget : Target
		{
			private ExplosionSpell m_Owner;

			public InternalTarget(ExplosionSpell owner)
			: base(12, false, TargetFlags.Harmful)
			{
				m_Owner = owner;
			}

			protected override void OnTarget(Mobile from, object o)
			{
				if (o is Mobile)
					m_Owner.Target((Mobile) o);
			}

			protected override void OnTargetFinish(Mobile from)
			{
				m_Owner.FinishSequence();
			}
		}
	}
}