/*
REWRITTEN BY XINEF
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "old_hillsbrad.h"

enum CaptainSkarloc
{
    SAY_ENTER                   = 0,
    SAY_TAUNT                   = 1,
    SAY_SLAY                    = 2,
    SAY_DEATH                   = 3,

    SPELL_HOLY_LIGHT            = 29427,
    SPELL_CLEANSE               = 29380,
    SPELL_HAMMER_OF_JUSTICE     = 13005,
    SPELL_HOLY_SHIELD           = 31904,
    SPELL_DEVOTION_AURA         = 8258,
    SPELL_CONSECRATION          = 38385,

    WAYPOINTS_COUNT             = 4,

    EVENT_INITIAL_TALK          = 1,
    EVENT_START_FIGHT           = 2,
    EVENT_SPELL_CLEANSE         = 10,
    EVENT_SPELL_HAMMER          = 11,
    EVENT_SPELL_HOLY_LIGHT      = 12,
    EVENT_SPELL_HOLY_SHIELD     = 13,
    EVENT_SPELL_CONSECRATION    = 14
};

const Position startPath[WAYPOINTS_COUNT] =
{
    {2008.38f, 281.57f, 65.70f, 0.0f},
    {2035.71f, 271.38f, 63.495f, 0.0f},
    {2049.12f, 252.31f, 62.855f, 0.0f},
    {2058.77f, 236.04f, 63.92f, 0.0f}
};

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

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

    struct boss_captain_skarlocAI : public ScriptedAI
    {
        boss_captain_skarlocAI(Creature* creature) : ScriptedAI(creature), summons(me) { }

        EventMap events;
        EventMap events2;
        SummonList summons;

        void Reset()
        {
            events.Reset();
            events2.Reset();
            summons.DespawnAll();
        }

        void JustSummoned(Creature* summon)
        {
            summons.Summon(summon);
            if (Creature* thrall = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_THRALL_GUID)))
                thrall->AI()->JustSummoned(summon);
            summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);

            if (summon->GetEntry() == NPC_SKARLOC_MOUNT)
                return;

            if (summons.size() == 1)
                summon->GetMotionMaster()->MovePoint(0, 2060.788f, 237.301f, 63.999f);
            else
                summon->GetMotionMaster()->MovePoint(0, 2056.870f, 234.853f, 63.839f);
        }

        void InitializeAI()
        {
            ScriptedAI::InitializeAI(); 

            Movement::PointsArray path;
            path.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
            for (uint8 i = 0; i < WAYPOINTS_COUNT; ++i) 
                path.push_back(G3D::Vector3(startPath[i].GetPositionX(), startPath[i].GetPositionY(), startPath[i].GetPositionZ()));

            me->GetMotionMaster()->MoveSplinePath(&path);
            me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
            me->Mount(SKARLOC_MOUNT_MODEL);
        }

        void MovementInform(uint32 type, uint32 id)
        {
            if (type != ESCORT_MOTION_TYPE)
                return;

            // Xinef: we can rely here on internal counting
            if (id == 1)
            {
                me->SummonCreature(NPC_DURNHOLDE_MAGE, 2038.549f, 273.303f, 63.420f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
                me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2032.810f, 269.416f, 63.561f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
            }
            else if (id == 2)
            {
                me->SummonCreature(NPC_SKARLOC_MOUNT, 2049.12f, 252.31f, 62.855f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN);
                me->Dismount();
                me->SetWalk(true);
                for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
                    if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
                        summon->SetWalk(true);
            }

            if (me->movespline->Finalized())
            {
                events2.ScheduleEvent(EVENT_INITIAL_TALK, 500);
                events2.ScheduleEvent(EVENT_START_FIGHT, 8000);
            }
        }

        void EnterCombat(Unit* /*who*/)
        {
            me->CastSpell(me, SPELL_DEVOTION_AURA, true);

            events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 15000);
            events.ScheduleEvent(EVENT_SPELL_CLEANSE, 6000);
            events.ScheduleEvent(EVENT_SPELL_HAMMER, 20000);
            events.ScheduleEvent(EVENT_SPELL_HOLY_SHIELD, 10000);
            if (IsHeroic())
                events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 1000);
        }

        void KilledUnit(Unit* victim)
        {
            Talk(SAY_SLAY);
        }

        void JustDied(Unit* /*killer*/)
        {
            Talk(SAY_DEATH);
            me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_SKARLOC_KILLED);
            me->GetInstanceScript()->SetData(DATA_THRALL_ADD_FLAG, 0);
        }

        void UpdateAI(uint32 diff)
        {
            events2.Update(diff);
            switch (events2.ExecuteEvent())
            {
                case EVENT_INITIAL_TALK:
                    Talk(SAY_ENTER);
                    break;
                case EVENT_START_FIGHT:
                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
                    me->SetInCombatWithZone();
                    for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
                        if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
                            if (summon->GetEntry() != NPC_SKARLOC_MOUNT)
                            {
                                summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
                                summon->SetInCombatWithZone();
                            }
                    break;
            }

            if (!UpdateVictim())
                return;

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

            switch (events.ExecuteEvent())
            {
                case EVENT_SPELL_HOLY_LIGHT:
                    me->CastSpell(me, SPELL_HOLY_LIGHT, false);
                    events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 20000);
                    break;
                case EVENT_SPELL_CLEANSE:
                    if (roll_chance_i(33))
                        Talk(SAY_TAUNT);
                    me->CastSpell(me, SPELL_CLEANSE, false);
                    events.ScheduleEvent(EVENT_SPELL_CLEANSE, 10000);
                    break;
                case EVENT_SPELL_HAMMER:
                    me->CastSpell(me->GetVictim(), SPELL_HAMMER_OF_JUSTICE, false);
                    events.ScheduleEvent(EVENT_SPELL_HAMMER, 30000);
                    break;
                case EVENT_SPELL_HOLY_SHIELD:
                    me->CastSpell(me, SPELL_CLEANSE, false);
                    events.ScheduleEvent(SPELL_HOLY_SHIELD, 30000);
                    break;
                case EVENT_SPELL_CONSECRATION:
                    me->CastSpell(me, SPELL_CONSECRATION, false);
                    events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 20000);
                    break;

            }

            DoMeleeAttackIfReady();
        }
    };

};

void AddSC_boss_captain_skarloc()
{
    new boss_captain_skarloc();
}
