/*
REWRITTEN BY XINEF
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "serpent_shrine.h"

enum Talk
{
    SAY_AGGRO                       = 0,
    SAY_GAIN_BLESSING               = 1,
    SAY_GAIN_ABILITY1               = 2,
    SAY_GAIN_ABILITY2               = 3,
    SAY_GAIN_ABILITY3               = 4,
    SAY_SLAY                        = 5,
    SAY_DEATH                       = 6
};

enum Spells
{
    SPELL_CATACLYSMIC_BOLT          = 38441,
    SPELL_SEAR_NOVA                 = 38445,
    SPELL_ENRAGE                    = 24318,
    SPELL_BLESSING_OF_THE_TIDES     = 38449
};

enum Misc
{
    MAX_ADVISORS                    = 3,
    NPC_FATHOM_GUARD_CARIBDIS       = 21964,
    NPC_FATHOM_GUARD_TIDALVESS      = 21965,
    NPC_FATHOM_GUARD_SHARKKIS       = 21966,
    NPC_SEER_OLUM                   = 22820,
    GO_CAGE                         = 185952,

    EVENT_SPELL_CATACLYSMIC_BOLT    = 1,
    EVENT_SPELL_ENRAGE              = 2,
    EVENT_SPELL_SEAR_NOVA           = 3,
    EVENT_HEALTH_CHECK              = 4,
    EVENT_KILL_TALK                 = 5
};

const Position advisorsPosition[MAX_ADVISORS+2] = 
{
    {459.61f, -534.81f, -7.54f, 3.82f},
    {463.83f, -540.23f, -7.54f, 3.15f},
    {459.94f, -547.28f, -7.54f, 2.42f},
    {448.37f, -544.71f, -7.54f, 0.00f},
    {457.37f, -544.71f, -7.54f, 0.00f}
};

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

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

        struct boss_fathomlord_karathressAI : public BossAI
        {
            boss_fathomlord_karathressAI(Creature* creature) : BossAI(creature, DATA_FATHOM_LORD_KARATHRESS)
            {
            }

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

                me->SummonCreature(NPC_FATHOM_GUARD_TIDALVESS, advisorsPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 600000);
                me->SummonCreature(NPC_FATHOM_GUARD_SHARKKIS, advisorsPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 600000);
                me->SummonCreature(NPC_FATHOM_GUARD_CARIBDIS, advisorsPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 600000);
            }

            void JustSummoned(Creature* summon)
            {
                summons.Summon(summon);
                if (summon->GetEntry() == NPC_SEER_OLUM)
                {
                    summon->SetWalk(true);
                    summon->GetMotionMaster()->MovePoint(0, advisorsPosition[MAX_ADVISORS+1], false);
                }
            }

            void SummonedCreatureDies(Creature* summon, Unit*)
            {
                summons.Despawn(summon);
                if (summon->GetEntry() == NPC_FATHOM_GUARD_TIDALVESS)
                    Talk(SAY_GAIN_ABILITY1);
                if (summon->GetEntry() == NPC_FATHOM_GUARD_SHARKKIS)
                    Talk(SAY_GAIN_ABILITY2);
                if (summon->GetEntry() == NPC_FATHOM_GUARD_CARIBDIS)
                    Talk(SAY_GAIN_ABILITY3);
            }

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

            void JustDied(Unit* killer)
            {
                Talk(SAY_DEATH);
                BossAI::JustDied(killer);
                me->SummonCreature(NPC_SEER_OLUM, advisorsPosition[MAX_ADVISORS], TEMPSUMMON_TIMED_DESPAWN, 3600000);
                if (GameObject* gobject = me->FindNearestGameObject(GO_CAGE, 100.0f))
                    gobject->SetGoState(GO_STATE_ACTIVE);
            }

            void EnterCombat(Unit* who)
            {
                BossAI::EnterCombat(who);
                Talk(SAY_AGGRO);
                me->CallForHelp(10.0f);

                events.ScheduleEvent(EVENT_SPELL_CATACLYSMIC_BOLT, 10000);
                events.ScheduleEvent(EVENT_SPELL_ENRAGE, 600000);
                events.ScheduleEvent(EVENT_SPELL_SEAR_NOVA, 25000);
                events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
            }

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

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

                switch (events.ExecuteEvent())
                {
                    case EVENT_SPELL_ENRAGE:
                        me->CastSpell(me, SPELL_ENRAGE, true);
                        break;
                    case EVENT_SPELL_CATACLYSMIC_BOLT:
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, PowerUsersSelector(me, POWER_MANA, 50.0f, true)))
                            me->CastSpell(target, SPELL_CATACLYSMIC_BOLT, false);
                        events.ScheduleEvent(EVENT_SPELL_CATACLYSMIC_BOLT, 6000);
                        break;
                    case EVENT_SPELL_SEAR_NOVA:
                        me->CastSpell(me, SPELL_SEAR_NOVA, false);
                        events.ScheduleEvent(EVENT_SPELL_SEAR_NOVA, 20000+urand(0, 20000));
                        break;
                    case EVENT_HEALTH_CHECK:
                        if (me->HealthBelowPct(76))
                        {
                            for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
                                if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
                                    if (summon->GetMaxHealth() > 500000)
                                        summon->CastSpell(me, SPELL_BLESSING_OF_THE_TIDES, true);

                            if (me->HasAura(SPELL_BLESSING_OF_THE_TIDES))
                                Talk(SAY_GAIN_BLESSING);
                            break;
                        }
                        events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
                        break;
                }

                DoMeleeAttackIfReady();
            }
        };
};

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

        class spell_karathress_power_of_caribdis_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_karathress_power_of_caribdis_AuraScript);

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

            void Register()
            {
                 OnEffectPeriodic += AuraEffectPeriodicFn(spell_karathress_power_of_caribdis_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
            }
        };

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

void AddSC_boss_fathomlord_karathress()
{
    new boss_fathomlord_karathress();
    new spell_karathress_power_of_caribdis();
}
