using System;
using System.Collections;

namespace Server.Spells.Spellweaving
{
	public class ArcaneEmpowermentSpell : ArcanistSpell
	{
		private static SpellInfo m_Info = new SpellInfo(
                "Arcane Empowerment", "Aslavdra",
				SpellCircle.Tenth, // 0.5 + 2.5 = 3s base cast delay
				-1
			);

        public override double RequiredSkill { get { return 24.0; } }
        public override int RequiredMana { get { return 50; } }

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

		public override bool CheckCast()
		{
			EmpowermentInfo info = m_Table[Caster] as EmpowermentInfo;

			if( info != null )
			{
				Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
				return false;
			}

			return base.CheckCast();
		}

		public override void OnCast()
		{
			if( CheckSequence() )
			{
				Caster.PlaySound( 0x5C1 );

                /* Tested in Osi.
                 * 
                 * Test values:
                 * 
                 * Without Arcane Focus:
				 *  24.0:  2% SDI, 10% Hits, Inc Heal, Inc Dispel, 16 secs.
				 * 120.0: 10% SDI, 10% Hits, Inc Heal, Inc Dispel, 20 secs.
				 * 
				 * With Arcane Focus Level One:
				 * 120.0: 15% SDI, 10% Hits, Inc Heal, Inc Dispel, 22 secs.
				 */
				int level = GetFocusLevel();
				double skill = Caster.Skills[SkillName.Spellweaving].Value;

				int duration = 15 + (int)Math.Floor( skill / 24 ) + ( level * 2 ); // 15 + Floor( Skill / 24 ) + ( FocusLevel * 2 )

				int sdiBonus = (int)Math.Floor( skill / 12 ) + ( level * 5 ); // Floor( Skill / 12 ) + ( FocusLevel * 5 )
				double healBonus = 0.2 + ( level / 10 ); // 0.2 + ( FocusLevel / 10 )
				int hitsBonus = 10; // As per Osi, value seems constant.
				int dispelBonus = (int)Math.Floor( skill / 12 ) + level; // Floor( Skill / 12 ) + FocusLevel

				m_Table[Caster] = new EmpowermentInfo( Caster, sdiBonus, healBonus, hitsBonus, dispelBonus, TimeSpan.FromSeconds( duration ) );

				BuffInfo.AddBuff( Caster, new BuffInfo( BuffIcon.ArcaneEmpowerment, 1031616, 1075808, TimeSpan.FromSeconds( duration ), Caster, new TextDefinition( String.Format( "{0}\t{1}", sdiBonus.ToString(), hitsBonus.ToString() ) ) ) );
			}

			FinishSequence();
		}

		private static Hashtable m_Table = new Hashtable();

		private class EmpowermentInfo
		{
			public Mobile m_Caster;
			public int m_SDIBonus;
			public double m_HealBonus;
			public int m_HitsBonus;
			public int m_DispelBonus;
			public ExpireTimer m_Timer;

			public EmpowermentInfo( Mobile caster, int sdiBonus, double healBonus, int hitsBonus, int dispelBonus, TimeSpan duration )
			{
				m_Caster = caster;
				m_SDIBonus = sdiBonus;
				m_HealBonus = healBonus;
				m_HitsBonus = hitsBonus;
				m_DispelBonus = dispelBonus;

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

		public static int GetSDIBonus( Mobile m )
		{
			EmpowermentInfo info = m_Table[m] as EmpowermentInfo;

			if( info == null )
				return 0;

			return info.m_SDIBonus;
		}

		public static void ApplyHealBonus( Mobile m, ref int points )
		{
			EmpowermentInfo info = m_Table[m] as EmpowermentInfo;

			if( info == null )
				return;

			/* Tested in Osi.
			 * 
			 * Test Values (Gift of Renewal, only spell with constant heals):
			 * 
			 * Without Arcane Focus:
			 *  48.0:  7 >  8
			 * 120.0: 10 > 12
			 * 
			 * With Arcane Focus Level One:
			 * 119.7: 10 > 13
			 * 120.0: 11 > 14
			 */
			double scalar = 1.0 + info.m_HealBonus;

			points = (int)Math.Floor( points * scalar );
		}

		public static int GetSummonHitsBonus( Mobile m )
		{
			EmpowermentInfo info = m_Table[m] as EmpowermentInfo;

			if( info == null )
				return 0;

			return info.m_HitsBonus;
		}

		public static int GetDispelBonus( Mobile m )
		{
			EmpowermentInfo info = m_Table[m] as EmpowermentInfo;

			if( info == null )
				return 0;

			return info.m_DispelBonus;
		}

		public static bool StopBuffing( Mobile m, bool message )
		{
			EmpowermentInfo info = m_Table[m] as EmpowermentInfo;

			if( info == null || info.m_Timer == null )
				return false;

			info.m_Timer.DoExpire( message );
			return true;
		}

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

				m_Table.Remove( m_Mobile );

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