using System;
using System.Collections;
using Server.Targeting;
using Server.Network;

namespace Server.Spells.Spellweaving
{
	public class GiftOfRenewalSpell : ArcanistSpell
	{
		private static SpellInfo m_Info = new SpellInfo(
                "Gift of Renewal", "Olorisstra",
//                 SpellCircle.Tenth, // 0.5 + 2.5 = 3s base cast delay
                SpellCircle.Fourth, // 0.5 + 1.0 = 1.5s base cast delay
				-1
			);

        public override double RequiredSkill { get { return 0.0; } }
        public override int RequiredMana { get { return 24; } }

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

		public override void OnCast()
		{
            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 is Server.Mobiles.Golem )
			   {
				  Caster.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500951 ); // You cannot heal that.
			   }
            else if( m_Table[m] != null )
            {
                Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
            }
            else if( Locked )
            {
                Caster.SendLocalizedMessage( 501789 ); // You must wait before trying again.
            }
            else if( CheckBSequence( m ) )
            {
                SpellHelper.Turn( Caster, m );

                Caster.FixedEffect( 0x374A, 10, 20 );
                Caster.PlaySound( 0x5C9 );

				if( m.Poisoned )
				{
					/* As per Osi, if character
					 * was poisoned prior to the
					 * Gift of Renewal, he is
					 * cured of it and the effect
					 * ends, with no cooldown delay.
					 */
					m.CurePoison( m );
				}
				else
				{
					/* Tested in Osi.
					 * 
					 * Test values:
					 * 
					 * Without Arcane Focus:
					 *  20.0 =  5 hits, 30 secs.
					 *  47.9 =  6 hits, 30 secs.
					 *  48.0 =  7 hits, 30 secs.
					 *  93.5 =  8 hits, 30 secs.
					 * 119.9 =  9 hits, 30 secs.
					 * 120.0 = 10 hits, 30 secs.
					 * 
					 * With Arcane Focus Level One:
					 *  93.5 =  9 hits, 40 secs.
					 * 119.9 = 10 hits, 40 secs.
					 * 120.0 = 11 hits, 40 secs.
					 */
					int level = GetFocusLevel();
					double skill = Caster.Skills[SkillName.Spellweaving].Value;

					int hitsPerRound = 10 + (int)Math.Floor( skill / 24 ) + level; // 5 + Floor( Skill / 24 ) + FocusLevel
					int duration = 40 + ( level * 10 ); // 30 + ( FocusLevel * 10 )                

					Activate( Caster, m, hitsPerRound, duration );

					Lock();
				}
            }

            FinishSequence();
        }

        private static Hashtable m_Table = new Hashtable();
        
        public static bool IsActive( Mobile m )
        {
            if( m_Table[m] != null )
                return true;
                
            return false;

        }
        
        public static void Activate( Mobile Caster, Mobile m, int hitsPerRound, int duration )
        {
				GiftOfRenewalInfo info = new GiftOfRenewalInfo( Caster, m, hitsPerRound, TimeSpan.FromSeconds( duration ) );

				m_Table[m] = info;

				info.m_InternalTimer = new InternalTimer( info );
				info.m_InternalTimer.Start();

				BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.GiftOfRenewal, 1031602, 1075797, TimeSpan.FromSeconds( duration ), m, new TextDefinition( hitsPerRound.ToString() ) ) );
        }

        private class GiftOfRenewalInfo
        {
			public Mobile m_Caster;
            public Mobile m_Defender;
            public int m_HitsPerRound;
            public ExpireTimer m_Timer;
            public InternalTimer m_InternalTimer;

            public GiftOfRenewalInfo( Mobile caster, Mobile defender, int hitsPerRound, TimeSpan duration )
            {
				m_Caster = caster;
                m_Defender = defender;
                m_HitsPerRound = hitsPerRound;

				m_Timer = new ExpireTimer( defender, duration );
				m_Timer.Start();
            }
        }

		private class InternalTimer : Timer
		{
			public GiftOfRenewalInfo m_Info;

			public InternalTimer( GiftOfRenewalInfo info ) : base( TimeSpan.FromSeconds( 2.0 ), TimeSpan.FromSeconds( 2.0 ) )
			{
				m_Info = info;
			}

			protected override void OnTick()
			{
				if( m_Table[m_Info.m_Defender] == null )
				{
					Stop();
					return;
				}

				if( !m_Info.m_Defender.Alive )
				{
					Stop();
					m_Info.m_Timer.DoExpire( false );
					return;
				}

				if( m_Info.m_Defender.Hits >= m_Info.m_Defender.HitsMax )
					return;

				int toHeal = m_Info.m_HitsPerRound;

				// SPELLWEAVING: Arcane Empowerment buff to heals
				ArcaneEmpowermentSpell.ApplyHealBonus( m_Info.m_Caster, ref toHeal );

				m_Info.m_Defender.Heal( toHeal, false );
				m_Info.m_Defender.FixedParticles( 0x376A, 9, 32, 5005, EffectLayer.Waist );
			}
		}

        private class ExpireTimer : Timer
        {
            private Mobile m_Mobile;

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

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

            public void DoExpire( bool message )
            {
                Stop();

                if( message )
                {
                    m_Mobile.PlaySound( 0x455 );
                    m_Mobile.SendLocalizedMessage( 1075071 ); // The Gift of Renewal has faded.
                }

                m_Table.Remove( m_Mobile );

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

        public class InternalTarget : Target
        {
            private GiftOfRenewalSpell m_Owner;

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

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