using System;
using System.Collections;

namespace Server.Spells.Spellweaving
{
	public class AttunementSpell : ArcanistSpell
	{
		private static SpellInfo m_Info = new SpellInfo(
                "Attunement", "Haeldril",
                SpellCircle.Second, // 0.5 + 0.5 = 1s base cast delay
				-1
			);

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

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

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

			if( info != null )
			{
				Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
				return false;
			}
			else if( Locked )
			{
				Caster.SendLocalizedMessage( 1075124 ); // You must wait before casting that spell again.
				return false;
			}
			else if( Caster.MeleeDamageAbsorb > 0 )
			{
				Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
				return false;
			}
			
			return base.CheckCast();
		}

        public override void OnCast()
        {
            if( CheckSequence() )
            {
                Caster.PlaySound( 0x5C3 );
                Caster.FixedParticles( 0x3728, 1, 13, 0x26B8, 0x455, 7, EffectLayer.Waist );
                Caster.FixedParticles( 0x3779, 1, 15, 0x251E, 0x3F, 7, EffectLayer.Waist );

                /* Tested in Osi.
                 * 
                 * Test values:
                 * 
                 * Without Arcane Focus:
                 *  20.0 = 21 points, 60 secs.
                 *  40.0 = 27 points.
                 *  60.0 = 33 points.
                 *  80.0 = 39 points.
                 * 100.0 = 45 points.
                 * 110.0 = 48 points.
                 * 120.0 = 51 points.
                 * 
                 * With Arcane Focus Level One:
                 *  40.0 = 33 points, 72 secs.
                 *  80.0 = 45 points.
                 * 100.0 = 51 points.
                 * 120.0 = 57 points.
                 * 
                 * As our theory rolls on, and as a Legendary Arcanist:
                 * Level 2: 63 points,  84 secs.
                 * Level 3: 69 points,  96 secs.
                 * Level 4: 75 points, 108 secs.
                 * Level 5: 81 points, 120 secs.
                 * Level 6: 87 points, 132 secs.
                 */
                int level = GetFocusLevel();
				double skill = Caster.Skills[SkillName.Spellweaving].Value;

                int shieldingPoints = 30 + (int)( Math.Floor( skill / 3 ) ) + ( level * 6 ); // 15 + Floor( Skill / 3 ) + ( FocusLevel * 6 )
                int duration = 60 + ( level * 12 ); // 60 + ( FocusLevel * 12 )

				m_Table[Caster] = new AttunementInfo( Caster, shieldingPoints, TimeSpan.FromSeconds( duration ) );

                Lock();

                BuffInfo.AddBuff( Caster, new BuffInfo( BuffIcon.Attunement, 1031604, 1075799, TimeSpan.FromSeconds( duration ), Caster, new TextDefinition( shieldingPoints.ToString() ) ) );
            }

            FinishSequence();
        }

        private static Hashtable m_Table = new Hashtable();

        private class AttunementInfo
        {
            public Mobile m_Defender;
            public ExpireTimer m_Timer;

            public AttunementInfo( Mobile defender, int shieldingPoints, TimeSpan duration )
            {
                m_Defender = defender;
                m_Defender.MeleeDamageAbsorb = shieldingPoints;

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

        public static void TryAbsorb( Mobile defender, ref int damage )
        {
            AttunementInfo info = m_Table[defender] as AttunementInfo;

			if( info == null || damage <= 0 || defender.MeleeDamageAbsorb <= 0 )
                return;

            int absorbed = Math.Min( damage, defender.MeleeDamageAbsorb );

            damage -= absorbed;
            defender.MeleeDamageAbsorb -= absorbed;

            defender.SendLocalizedMessage( 1075127, String.Format( "{0}\t{1}", absorbed, defender.MeleeDamageAbsorb ) ); // ~1_damage~ point(s) of damage have been absorbed. A total of ~2_remaining~ point(s) of shielding remain.

            if( defender.MeleeDamageAbsorb <= 0 )
                StopAbsorbing( defender, true );

            if( damage == 0 )
                damage = -1;
        }

        public static bool IsAbsorbing( Mobile m )
        {
            AttunementInfo info = m_Table[m] as AttunementInfo;

            return info != null;            
        }

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

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

                m_Mobile.MeleeDamageAbsorb = 0;

                if( message )
                {
                    m_Mobile.SendLocalizedMessage( 1075126 ); // Your attunement fades.
                    m_Mobile.PlaySound( 0x1F8 );
                }

                m_Table.Remove( m_Mobile );

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