using Server.Items;
using Server.Mobiles;
using System;

/*When activated the shield user will execute a shield bash on successfully hitting or parrying their opponent 
  causing physical damage and paralyzing their opponent based on parry skill, best weapon skill, and mastery level.*/

namespace Server.Spells.SkillMasteries
{
    public class ShieldBashSpell : SkillMasterySpell
    {
        private static readonly SpellInfo m_Info = new SpellInfo(
                "Shield Bash", "",
                -1,
                9002
            );

        public override int RequiredMana => 40;
        public override bool BlocksMovement => false;
        public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0);

        public override SkillName CastSkill => SkillName.Parry;

        public double Multiplier => (Caster.Skills[GetBestSkill()].Value + Caster.Skills[SkillName.Parry].Value + (GetMasteryLevel() * 40)) / 360;

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

        public override bool CheckCast()
        {
            if (!HasShield())
                return false;

            if (HasSpell(Caster, GetType()))
                return false;

            return base.CheckCast();
        }

        public override void OnCast()
        {
            if (CheckSequence())
            {
                Caster.FixedParticles(0x376A, 9, 32, 5030, 1168, 0, EffectLayer.Waist, 0);
                Caster.PlaySound(0x51A);

                TimeSpan duration = TimeSpan.FromSeconds((int)Math.Max(3, 5.0 * Multiplier));

                Caster.SendLocalizedMessage(1156022); // You ready your shield.

                Expires = DateTime.UtcNow + duration;
                BeginTimer();

                BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.ShieldBash, 1155923, 1156093, duration, Caster));
                //Places you in an offensive stance which allows you to strike your target with your shield on your next successful attack or parry.
            }

            FinishSequence();
        }

        public override bool OnTick()
        {
            if (!HasShield())
            {
                Expire();
                return false;
            }

            return base.OnTick();
        }

        private bool HasShield()
        {
            if (!Caster.Player)
                return true;

            BaseShield shield = Caster.FindItemOnLayer(Layer.TwoHanded) as BaseShield;

            if (shield == null)
            {
                Caster.SendLocalizedMessage(1156096); // You must be wielding a shield to use this ability!
                return false;
            }

            return true;
        }

        public override void EndEffects()
        {
            BuffInfo.RemoveBuff(Caster, BuffIcon.ShieldBash);
        }

        public override void OnHit(Mobile defender, ref int damage)
        {
            if (!HasShield())
            {
                Expire();
                return;
            }

            Caster.SendLocalizedMessage(1156027); // You bash you target with your shield!
            bool pvp = Caster is PlayerMobile && defender is PlayerMobile;

            double multiplier = Multiplier;

            damage = pvp ? (int)(damage * (multiplier * 3)) : (int)(damage * (multiplier * 7));

            if (pvp && damage > 35)
                damage = 35;

            Server.Timer.DelayCall(TimeSpan.FromMilliseconds(100), () =>
                {
                    if (defender.Alive)
                    {
                        CheckParalyze(defender, TimeSpan.FromSeconds(pvp ? multiplier * 3 : multiplier * 6));
                    }
                });

            Expire();
        }

        private SkillName GetBestSkill()
        {
            double swrd = Caster.Skills[SkillName.Swords].Value;
            double fenc = Caster.Skills[SkillName.Fencing].Value;
            double mcng = Caster.Skills[SkillName.Macing].Value;
            double wres = Caster.Skills[SkillName.Wrestling].Value;

            SkillName sk = SkillName.Swords;
            double val = swrd;

            if (fenc > val)
            {
                sk = SkillName.Fencing;
                val = fenc;
            }
            if (mcng > val)
            {
                sk = SkillName.Macing;
                val = mcng;
            }
            if (wres > val)
            {
                sk = SkillName.Wrestling;
            }

            return sk;
        }

        private void CheckParalyze(Mobile defender, TimeSpan duration)
        {
            if (ParalyzingBlow.IsImmune(defender))
            {
                Caster.SendLocalizedMessage(1070804); // Your target resists paralysis.
                defender.SendLocalizedMessage(1070813); // You resist paralysis.
                return;
            }

            defender.FixedEffect(0x376A, 9, 32);
            defender.PlaySound(0x204);

            Caster.SendLocalizedMessage(1060163); // You deliver a paralyzing blow!
            defender.SendLocalizedMessage(1060164); // The attack has temporarily paralyzed you!

            // Treat it as paralyze not as freeze, effect must be removed when damaged.
            defender.Paralyze(duration);

            ParalyzingBlow.BeginImmunity(defender, duration);
        }

        public override void OnParried(Mobile attacker)
        {
            BaseWeapon wep = Caster.Weapon as BaseWeapon;

            if (wep != null)
                wep.OnHit(Caster, attacker, 1.0);
        }
    }
}
