/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "culling_of_stratholme.h"
#include "SpellScript.h"

enum Spells
{
    SPELL_SHADOW_BOLT_N                         = 57725,
    SPELL_SHADOW_BOLT_H                         = 58827,
    SPELL_STEAL_FLESH_CHANNEL                   = 52708,
    SPELL_STEAL_FLESH_TARGET                    = 52711,
    SPELL_STEAL_FLESH_CASTER                    = 52712,
    SPELL_SUMMON_GHOULS                         = 52451,
    SPELL_EXPLODE_GHOUL_N                       = 52480,
    SPELL_EXPLODE_GHOUL_H                       = 58825,
    SPELL_CURSE_OF_TWISTED_FAITH                = 58845,
};

enum Events
{
    EVENT_SPELL_SHADOW_BOLT                     = 1,
    EVENT_SPELL_STEAL_FLESH                     = 2,
    EVENT_SPELL_SUMMON_GHOULS                   = 3,
    EVENT_EXPLODE_GHOUL                         = 4,
    EVENT_SPELL_CURSE                           = 5,
};

enum Yells
{
    SAY_AGGRO                                   = 0,
    SAY_SPAWN                                   = 1,
    SAY_SLAY                                    = 2,
    SAY_DEATH                                   = 3,
    SAY_EXPLODE_GHOUL                           = 4,
    SAY_STEAL_FLESH                             = 5,
    SAY_SUMMON_GHOULS                           = 6
};

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

    CreatureAI* GetAI(Creature* creature) const
    {
        return new boss_salrammAI (creature);
    }

    struct boss_salrammAI : public ScriptedAI
    {
        boss_salrammAI(Creature* c) : ScriptedAI(c), summons(me)
        {
            Talk(SAY_SPAWN);
        }

        EventMap events;
        SummonList summons;
        void Reset() 
        { 
            events.Reset();
            summons.DespawnAll();
        }

        void JustSummoned(Creature* cr) { summons.Summon(cr); }

        void EnterCombat(Unit* /*who*/)
        {
            Talk(SAY_AGGRO);
            events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, 7000);
            events.ScheduleEvent(EVENT_SPELL_STEAL_FLESH, 11000);
            events.ScheduleEvent(EVENT_SPELL_SUMMON_GHOULS, 16000);
            events.ScheduleEvent(EVENT_EXPLODE_GHOUL, 22000);
            if (IsHeroic())
                events.ScheduleEvent(EVENT_SPELL_CURSE, 25000);
        }

        void JustDied(Unit* /*killer*/)
        {
            summons.DespawnAll();
            Talk(SAY_DEATH);
        }

        void KilledUnit(Unit* victim)
        {
            if (!urand(0,1))
                return;

            Talk(SAY_SLAY);
        }

        void ExplodeGhoul()
        {
            for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
                if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr)))
                    if (cr->IsAlive())
                    {
                        me->CastSpell(cr, DUNGEON_MODE(SPELL_EXPLODE_GHOUL_N, SPELL_EXPLODE_GHOUL_H), false);
                        return;
                    }
        }

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

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

            switch (events.GetEvent())
            {
                case EVENT_SPELL_SHADOW_BOLT:
                    me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_SHADOW_BOLT_N, SPELL_SHADOW_BOLT_H), false);
                    events.RepeatEvent(10000);
                    break;
                case EVENT_SPELL_STEAL_FLESH:
                    if (!urand(0,2))
                        Talk(SAY_STEAL_FLESH);
                    me->CastSpell(me->GetVictim(), SPELL_STEAL_FLESH_CHANNEL, false);
                    events.RepeatEvent(12000);
                    break;
                case EVENT_SPELL_SUMMON_GHOULS:
                    if (!urand(0,2))
                        Talk(SAY_SUMMON_GHOULS);
                    me->CastSpell(me, SPELL_SUMMON_GHOULS, false);
                    events.RepeatEvent(10000);
                    break;
                case EVENT_EXPLODE_GHOUL:
                    if (!urand(0,2))
                        Talk(SAY_EXPLODE_GHOUL);
                    ExplodeGhoul();
                    events.RepeatEvent(15000);
                    break;
                case EVENT_SPELL_CURSE:
                    me->CastSpell(me->GetVictim(), SPELL_CURSE_OF_TWISTED_FAITH, false);
                    events.RepeatEvent(30000);
                    break;
            }

            DoMeleeAttackIfReady();
        }
    };

};

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

        class spell_boss_salramm_steal_flesh_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_boss_salramm_steal_flesh_AuraScript);

            void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
            {
                Unit* caster = GetCaster();
                Unit* target = GetUnitOwner();
                if (caster)
                {
                    caster->CastSpell(caster, SPELL_STEAL_FLESH_CASTER, true);
                    caster->CastSpell(target, SPELL_STEAL_FLESH_TARGET, true);
                }
            }

            void Register()
            {
                AfterEffectRemove += AuraEffectRemoveFn(spell_boss_salramm_steal_flesh_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
            }
        };

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

void AddSC_boss_salramm()
{
    new boss_salramm();
    new spell_boss_salramm_steal_flesh();
}
