using System;
using System.Collections;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Gumps;
using Server.Targeting;
using Server.Regions;

namespace Server.Spells.Spellweaving
{
	public class GiftOfLifeSpell : ArcanistSpell
	{
		private static SpellInfo m_Info = new SpellInfo(
                "Gift of Life", "Illorae",
                SpellCircle.Fourteenth, // 0.5 + 3.5 = 4s base cast delay
				-1
			);

        public override double RequiredSkill { get { return 38.0; } }
        public override int RequiredMana { get { return 70; } }

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

        public static void Initialize()
        {
            EventSink.Login += new LoginEventHandler( OnLogin );
        }

        public override void OnCast()
        {
            if ( Caster.Map == Map.Auberon )
					Caster.SendLocalizedMessage( 501802 ); // Thy spell doth not appear to work...
            else
               Caster.Target = new InternalTarget( this );
        }

        public void Target( Mobile m )
        {
            if( !Caster.CanSee( m ) )
            {
                Caster.SendLocalizedMessage( 500237 ); // Target can not be seen.
            }
            else if( m.IsDeadBondedPet )
            {
                // As per Osi: Nothing happens.
            }
            else if( m != Caster && ( !( m is BaseCreature ) || !((BaseCreature)m).IsBonded || ((BaseCreature)m).GetMaster() != Caster ) )
            {
                Caster.SendLocalizedMessage( 1072077 ); // You may only cast this spell on yourself or a bonded pet.
            }
            else if( m_Table[m] != null )
            {
                Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
            }
            else if( CheckBSequence( m ) )
            {
                SpellHelper.Turn( Caster, m );

                m.PlaySound( 0x244 );
                m.FixedParticles( 0x3709, 1, 30, 0x26ED, 5, 2, EffectLayer.Waist );
                m.FixedParticles( 0x376A, 1, 30, 0x251E, 5, 3, EffectLayer.Waist );

                if( Caster == m )
                    Caster.SendLocalizedMessage( 1074774 ); // You weave powerful magic, protecting yourself from death.
                else
                    Caster.SendLocalizedMessage( 1074775 ); // You weave powerful magic, protecting your pet from death.

                /* Tested in Osi.
                 * 
                 * Test values:
                 * 
                 * Without Arcane Focus:
                 *  40.0 = 120 secs.
                 *  47.9 = 120 secs.
                 *  48.0 = 240 secs.
                 *  50.0 = 240 secs.
                 *  60.0 = 240 secs.
                 *  80.0 = 360 secs.
                 *  93.5 = 360 secs.
                 * 100.0 = 480 secs.
                 * 120.0 = 600 secs.
                 * 
                 * With Arcane Focus Level One:
                 *  40.0 = 180 secs.
                 */
                int level = GetFocusLevel();
				double skill = Caster.Skills[SkillName.Spellweaving].Value;

                int duration = ( Math.Max( 1, (int)Math.Floor( skill / 24 ) ) * 120 ) + ( level * 60 ); // ( Floor( Skill / 24 ) * 120 ) + ( FocusLevel * 60 )
                
               if ( Caster.HeadArmor is Server.Items.HelmOfSpirituality && ((Server.Items.HelmOfSpirituality)Caster.HeadArmor).Bonus > 4 )
                  duration += 20;
                
                ExpireTimer t = new ExpireTimer( m, TimeSpan.FromSeconds( duration ) );
                t.Start();

                m_Table[m] = t;

                BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.GiftOfLife, 1031615, 1075807, TimeSpan.FromSeconds( duration ), m, true ) );                                
            }

            FinishSequence();
        }

        private static Hashtable m_Table = new Hashtable();

        public static void HandleDeath( Mobile m )
        {
            if( m_Table[m] != null )
            {
                if( m.Player && m.NetState != null && !m.Alive )
                  m.Frozen = true;
                  
                Timer.DelayCall( TimeSpan.FromSeconds( 2 ), new TimerStateCallback( HandleDeath_OnCallback ), m );
            }
        }
        
        public static bool IsActive( Mobile m )
        {
            if( m_Table[m] != null )
                return true;
                
            return false;

        }

        private static void HandleDeath_OnCallback( object state )
        {
            HandleDeath_OnCallback( state as Mobile );
        }

        private static void HandleDeath_OnCallback( Mobile m )
        {
            bool doExpire = true;
            GroupDungeonRegion groupdungeonregion = (GroupDungeonRegion) Region.Find( m.Location, m.Map ).GetRegion( typeof( GroupDungeonRegion ) );

			if( m.Map == Map.Auberon || m.Map == Map.Underworld || KhaldunRevenant.IsInsideKhaldun( m ) || groupdungeonregion != null )
			{
				Mobile r = m;
				m.Frozen = false;

				if( m is BaseCreature )
					r = ( (BaseCreature)m ).GetMaster();

				if( r != null )
					r.SendLocalizedMessage( 1010395 ); // The veil of death in this area is too strong and resists thy efforts to restore life.
			}
			else if( m.Player && m.NetState != null && !m.Alive )
			{
				m.CloseGump( typeof( ResurrectGump ) );
// 				m.SendGump( new ResurrectGump( m ) );
				m.PlaySound( 0x214 );
				m.FixedEffect( 0x376A, 10, 16 );

				m.Resurrect();
				m.Frozen = false;
				
				if ( m.Fame > 0 )
				{
					int amount = m.Fame / 10;

					Misc.Titles.AwardFame( m, -amount, true );
				}
			}
			else if( m.IsDeadBondedPet )
			{
				BaseCreature pet = m as BaseCreature;

				if( pet != null )
				{
					Mobile master = pet.GetMaster();

					if( master != null && master.InRange( pet, 12 ) && master.NetState != null )
					{
						master.SendGump( new PetResurrectGump( master, pet ) );
					}
					else
					{
						List<Mobile> friends = pet.Friends;

						for( int i = 0; friends != null && i < friends.Count; i++ )
						{
							Mobile friend = friends[i];

							if( friend.InRange( pet, 12 ) && friend.NetState != null )
							{
								friend.SendGump( new PetResurrectGump( friend, pet ) );
								break;
							}
						}
					}
				}
			}
			else if( !m.Player && !m.Alive )
			{
				m.Resurrect();

				m.Hits = m.HitsMax / 2;
				m.Stam = m.StamMax;
				m.Mana = m.ManaMax;
			}
			else
			{
				doExpire = false;
				m.Frozen = false;
			}

            if( doExpire )
            {
                ExpireTimer t = m_Table[m] as ExpireTimer;

                if( t != null )
                    t.DoExpire();
            }
        }

        public static void OnLogin( LoginEventArgs e )
        {
            Mobile m = e.Mobile;

            if( m == null || m.Alive || m_Table[m] == null )
                return;

            HandleDeath_OnCallback( m );
        }

        private class ExpireTimer : Timer
        {
            private Mobile m_Mobile;

            public ExpireTimer( Mobile m, TimeSpan delay ) : base( delay )
            {
                m_Mobile = m;
            }

            protected override void OnTick()
            {
                DoExpire();
            }

            public void DoExpire()
            {
                Stop();

                m_Mobile.SendLocalizedMessage( 1074776 ); // You are no longer protected with Gift of Life.
                m_Table.Remove( m_Mobile );

                BuffInfo.RemoveBuff( m_Mobile, BuffIcon.GiftOfLife );
            }
        }

        public class InternalTarget : Target
        {
            private GiftOfLifeSpell m_Owner;

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

            protected override void OnTarget( Mobile m, object o )
            {
				if( o is Mobile )
				{
					m_Owner.Target( (Mobile)o );
				}
				else
				{
					m.SendLocalizedMessage( 1072077 ); // You may only cast this spell on yourself or a bonded pet.
				}
            }

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