/*
REWRITTEN BY XINEF
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "black_temple.h"

enum Says
{
    SAY_TAUNT                       = 0,
    SAY_AGGRO                       = 1,
    SAY_SPELL                       = 2,
    SAY_SLAY                        = 3,
    SAY_ENRAGE                      = 4,
    SAY_DEATH                       = 5,
    SAY_EMOTE_FRENZY                = 6
};

enum Spells
{
    SPELL_PRISMATIC_AURA_SHADOW     = 40880,
    SPELL_PRISMATIC_AURA_FIRE       = 40882,
    SPELL_PRISMATIC_AURA_NATURE     = 40883,
    SPELL_PRISMATIC_AURA_ARCANE     = 40891,
    SPELL_PRISMATIC_AURA_FROST      = 40896,
    SPELL_PRISMATIC_AURA_HOLY       = 40897,
    SPELL_SABER_LASH_AURA           = 40816,
    SPELL_SABER_LASH                = 40810,
    SPELL_SILENCING_SHRIEK          = 40823,
    SPELL_RANDOM_PERIODIC           = 40867,
    SPELL_SINFUL_PERIODIC           = 40862,
    SPELL_SINISTER_PERIODIC         = 40863,
    SPELL_VILE_PERIODIC             = 40865,
    SPELL_WICKED_PERIODIC           = 40866,
    SPELL_FATAL_ATTRACTION          = 40869,
    SPELL_FATAL_ATTRACTION_AURA     = 41001,
    SPELL_FATAL_ATTRACTION_DAMAGE   = 40871,
    SPELL_ENRAGE                    = 45078,
    SPELL_FRENZY                    = 40683,
    SPELL_SABER_LASH_IMMUNITY       = 43690
};

enum Misc
{
    EVENT_KILL_TALK                 = 1,
    EVENT_CHECK_HEALTH              = 2,
    EVENT_RANDOM_TALK               = 3,
    EVENT_SPELL_ENRAGE              = 4,
    EVENT_SPELL_PRISMATIC_AURA      = 5,
    EVENT_SPELL_SILENCING_SHRIEK    = 6,
    EVENT_SPELL_FATAL_ATTRACTION    = 7,
    EVENT_SPELL_SABER_LASH          = 8
};

class boss_mother_shahraz : public CreatureScript
{
    public:
        boss_mother_shahraz() : CreatureScript("boss_mother_shahraz") { }

        CreatureAI* GetAI(Creature* creature) const
        {
            return GetInstanceAI<boss_shahrazAI>(creature);
        }

        struct boss_shahrazAI : public BossAI
        {
            boss_shahrazAI(Creature* creature) : BossAI(creature, DATA_MOTHER_SHAHRAZ)
            {
            }

            void Reset()
            {
                BossAI::Reset();
            }

            void EnterCombat(Unit* who)
            {
                BossAI::EnterCombat(who);
                Talk(SAY_AGGRO);

                me->CastSpell(me, SPELL_SABER_LASH_AURA, true);
                me->CastSpell(me, SPELL_RANDOM_PERIODIC, true);
                events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
                events.ScheduleEvent(EVENT_RANDOM_TALK, 60000);
                events.ScheduleEvent(EVENT_SPELL_PRISMATIC_AURA, 0);
                events.ScheduleEvent(EVENT_SPELL_ENRAGE, 600000);
                events.ScheduleEvent(EVENT_SPELL_SILENCING_SHRIEK, 30000);
                events.ScheduleEvent(EVENT_SPELL_FATAL_ATTRACTION, 50000);
                events.ScheduleEvent(EVENT_SPELL_SABER_LASH, 4000);
            }

            void KilledUnit(Unit* /*victim*/)
            {
                if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
                {
                    Talk(SAY_SLAY);
                    events.ScheduleEvent(EVENT_KILL_TALK, 6000);
                }
            }

            void JustDied(Unit* killer)
            {
                BossAI::JustDied(killer);
                Talk(SAY_DEATH);
            }

            void UpdateAI(uint32 diff)
            {
                if (!UpdateVictim())
                    return;

                events.Update(diff);
                if (me->HasUnitState(UNIT_STATE_CASTING))
                    return;

                switch (events.ExecuteEvent())
                {
                    case EVENT_CHECK_HEALTH:
                        if (HealthBelowPct(10))
                        {
                            me->CastSpell(me, SPELL_FRENZY, true);
                            Talk(SAY_EMOTE_FRENZY);
                            break;
                        }
                        events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
                        break;
                    case EVENT_SPELL_ENRAGE:
                        me->CastSpell(me, SPELL_ENRAGE, true);
                        Talk(SAY_ENRAGE);
                        break;
                    case EVENT_RANDOM_TALK:
                        Talk(SAY_TAUNT);
                        events.ScheduleEvent(EVENT_RANDOM_TALK, urand(60000, 120000));
                        break;
                    case EVENT_SPELL_SABER_LASH:
                        me->CastSpell(me->GetVictim(), SPELL_SABER_LASH, false);
                        events.ScheduleEvent(EVENT_SPELL_SABER_LASH, 30000);
                        break;
                    case EVENT_SPELL_PRISMATIC_AURA:
                        me->CastSpell(me, RAND(SPELL_PRISMATIC_AURA_SHADOW, SPELL_PRISMATIC_AURA_FIRE, SPELL_PRISMATIC_AURA_NATURE, SPELL_PRISMATIC_AURA_ARCANE, SPELL_PRISMATIC_AURA_FROST, SPELL_PRISMATIC_AURA_HOLY), false);
                        events.ScheduleEvent(EVENT_SPELL_PRISMATIC_AURA, 15000);
                        break;
                    case EVENT_SPELL_SILENCING_SHRIEK:
                        me->CastSpell(me, SPELL_SILENCING_SHRIEK, false);
                        events.ScheduleEvent(EVENT_SPELL_SILENCING_SHRIEK, 30000);
                        break;
                    case EVENT_SPELL_FATAL_ATTRACTION:
                        Talk(SAY_SPELL);
                        me->CastCustomSpell(SPELL_FATAL_ATTRACTION, SPELLVALUE_MAX_TARGETS, 3, me, false);
                        events.ScheduleEvent(EVENT_SPELL_FATAL_ATTRACTION, 60000);
                        break;
                }

                DoMeleeAttackIfReady();
            }
        };
};

class spell_mother_shahraz_random_periodic : public SpellScriptLoader
{
    public:
        spell_mother_shahraz_random_periodic() : SpellScriptLoader("spell_mother_shahraz_random_periodic") { }

        class spell_mother_shahraz_random_periodic_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_mother_shahraz_random_periodic_AuraScript);

            void Update(AuraEffect const* effect)
            {                
                PreventDefaultAction();
                if (effect->GetTickNumber()%5 == 1)
                    GetUnitOwner()->CastSpell(GetUnitOwner(), RAND(SPELL_SINFUL_PERIODIC, SPELL_SINISTER_PERIODIC, SPELL_VILE_PERIODIC, SPELL_WICKED_PERIODIC), true);
            }

            void Register()
            {
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_random_periodic_AuraScript::Update, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_mother_shahraz_random_periodic_AuraScript();
        }
};

class spell_mother_shahraz_beam_periodic : public SpellScriptLoader
{
    public:
        spell_mother_shahraz_beam_periodic() : SpellScriptLoader("spell_mother_shahraz_beam_periodic") { }

        class spell_mother_shahraz_beam_periodic_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_mother_shahraz_beam_periodic_AuraScript);

            void Update(AuraEffect const* effect)
            {                
                PreventDefaultAction();
                if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
                    GetUnitOwner()->CastSpell(target, GetSpellInfo()->Effects[effect->GetEffIndex()].TriggerSpell, true);
            }

            void Register()
            {
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_beam_periodic_AuraScript::Update, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_mother_shahraz_beam_periodic_AuraScript();
        }
};

class spell_mother_shahraz_saber_lash : public SpellScriptLoader
{
    public:
        spell_mother_shahraz_saber_lash() : SpellScriptLoader("spell_mother_shahraz_saber_lash") { }

        class spell_mother_shahraz_saber_lash_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_mother_shahraz_saber_lash_AuraScript);

            bool CheckProc(ProcEventInfo& eventInfo)
            {
                return false;
            }

            void Update(AuraEffect const* effect)
            {                
                PreventDefaultAction();
                if (Unit* target = GetUnitOwner()->GetVictim())
                    GetUnitOwner()->CastSpell(target, GetSpellInfo()->Effects[effect->GetEffIndex()].TriggerSpell, true);
            }

            void Register()
            {
                DoCheckProc += AuraCheckProcFn(spell_mother_shahraz_saber_lash_AuraScript::CheckProc);
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_saber_lash_AuraScript::Update, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_mother_shahraz_saber_lash_AuraScript();
        }
};

class spell_mother_shahraz_fatal_attraction : public SpellScriptLoader
{
    public:
        spell_mother_shahraz_fatal_attraction() : SpellScriptLoader("spell_mother_shahraz_fatal_attraction") { }

        class spell_mother_shahraz_fatal_attraction_SpellScript : public SpellScript
        {
            PrepareSpellScript(spell_mother_shahraz_fatal_attraction_SpellScript);

            void FilterTargets(std::list<WorldObject*>& targets)
            {
                targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_SABER_LASH_IMMUNITY));
                if (targets.size() <= 1)
                    FinishCast(SPELL_FAILED_DONT_REPORT);
            }

            void SetDest(SpellDestination& dest)
            {
                std::list<Spell::TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
                for (std::list<Spell::TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
                    if (Unit* target = ObjectAccessor::GetUnit(*GetCaster(), ihit->targetGUID))
                    {
                        dest.Relocate(*target);
                        if (roll_chance_i(50))
                            break;
                    }
            }

            void HandleTeleportUnits(SpellEffIndex effIndex)
            {
                if (Unit* target = GetHitUnit())
                    GetCaster()->CastSpell(target, SPELL_FATAL_ATTRACTION_AURA, true);
            }

            void Register()
            {
                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mother_shahraz_fatal_attraction_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
                OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_mother_shahraz_fatal_attraction_SpellScript::SetDest, EFFECT_1, TARGET_DEST_CASTER_RANDOM);
                OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction_SpellScript::HandleTeleportUnits, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS);
            }
        };

        SpellScript* GetSpellScript() const
        {
            return new spell_mother_shahraz_fatal_attraction_SpellScript();
        }
};

class spell_mother_shahraz_fatal_attraction_dummy : public SpellScriptLoader
{
    public:
        spell_mother_shahraz_fatal_attraction_dummy() : SpellScriptLoader("spell_mother_shahraz_fatal_attraction_dummy") { }

        class spell_mother_shahraz_fatal_attraction_dummy_SpellScript : public SpellScript
        {
            PrepareSpellScript(spell_mother_shahraz_fatal_attraction_dummy_SpellScript);

            void HandleDummy(SpellEffIndex effIndex)
            {
                if (Unit* target = GetHitUnit())
                {
                    target->CastSpell(target, SPELL_FATAL_ATTRACTION_DAMAGE, true);
                    if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_FATAL_ATTRACTION_AURA, EFFECT_1))
                        aurEff->SetAmount(aurEff->GetTickNumber());
                }
            }

            void Register()
            {
                OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
            }
        };

        SpellScript* GetSpellScript() const
        {
            return new spell_mother_shahraz_fatal_attraction_dummy_SpellScript();
        }
};

class spell_mother_shahraz_fatal_attraction_aura : public SpellScriptLoader
{
    public:
        spell_mother_shahraz_fatal_attraction_aura() : SpellScriptLoader("spell_mother_shahraz_fatal_attraction_aura") { }

        class spell_mother_shahraz_fatal_attraction_aura_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_mother_shahraz_fatal_attraction_aura_AuraScript);

            void Update(AuraEffect const* effect)
            {                
                if (effect->GetTickNumber() > uint32(effect->GetAmount()+1))
                {
                    PreventDefaultAction();
                    SetDuration(0);
                }
            }

            void Register()
            {
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_fatal_attraction_aura_AuraScript::Update, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_mother_shahraz_fatal_attraction_aura_AuraScript();
        }
};

void AddSC_boss_mother_shahraz()
{
    new boss_mother_shahraz();
    new spell_mother_shahraz_random_periodic();
    new spell_mother_shahraz_beam_periodic();
    new spell_mother_shahraz_saber_lash();
    new spell_mother_shahraz_fatal_attraction();
    new spell_mother_shahraz_fatal_attraction_dummy();
    new spell_mother_shahraz_fatal_attraction_aura();
}
