/*
REWRITTEN BY XINEF
*/

#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "shadowfang_keep.h"
#include "TemporarySummon.h"


enum Creatures
{
    NPC_ASH                 = 3850,
    NPC_ADA                 = 3849,
    NPC_ARCHMAGE_ARUGAL     = 4275,
    NPC_ARUGAL_VOIDWALKER   = 4627
};


class instance_shadowfang_keep : public InstanceMapScript
{
    public:
        instance_shadowfang_keep() : InstanceMapScript("instance_shadowfang_keep", 33) { }

        InstanceScript* GetInstanceScript(InstanceMap* map) const
        {
            return new instance_shadowfang_keep_InstanceMapScript(map);
        }

        struct instance_shadowfang_keep_InstanceMapScript : public InstanceScript
        {
            instance_shadowfang_keep_InstanceMapScript(Map* map) : InstanceScript(map) { }

            void Initialize()
            {
                memset(&_encounters, 0, sizeof(_encounters));
            }

            void OnGameObjectCreate(GameObject* gameobject)
            {
                switch (gameobject->GetEntry())
                {
                    case GO_COURTYARD_DOOR:
                        if (_encounters[TYPE_COURTYARD] == DONE)
                            HandleGameObject(0, true, gameobject);
                        break;
                    case GO_SORCERER_DOOR:
                        if (_encounters[TYPE_FENRUS_THE_DEVOURER] == DONE)
                            HandleGameObject(0, true, gameobject);
                        break;
                    case GO_ARUGAL_DOOR:
                        if (_encounters[TYPE_WOLF_MASTER_NANDOS] == DONE)
                            HandleGameObject(0, true, gameobject);
                        break;
                }
            }

            void SetData(uint32 type, uint32 data)
            {
                switch (type)
                {
                    case TYPE_COURTYARD:
                    case TYPE_FENRUS_THE_DEVOURER:
                    case TYPE_WOLF_MASTER_NANDOS:
                        _encounters[type] = data;
                        break;
                }

                if (data == DONE)
                    SaveToDB();
            }

            std::string GetSaveData()
            {
                std::ostringstream saveStream;
                saveStream << "S K " << _encounters[0] << ' ' << _encounters[1] << ' ' << _encounters[2];
                return saveStream.str();
            }

            void Load(const char* in)
            {
                if (!in)
                    return;

                char dataHead1, dataHead2;
                std::istringstream loadStream(in);
                loadStream >> dataHead1 >> dataHead2;
                if (dataHead1 == 'S' && dataHead2 == 'K')
                {
                    for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
                    {
                        loadStream >> _encounters[i];
                        if (_encounters[i] == IN_PROGRESS)
                            _encounters[i] = NOT_STARTED;
                    }
                }
            }

        private:
            uint32 _encounters[MAX_ENCOUNTERS];
        };

};

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

        class spell_shadowfang_keep_haunting_spirits_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_shadowfang_keep_haunting_spirits_AuraScript);

            void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
            {
                isPeriodic = true;
                amplitude = irand(30*IN_MILLISECONDS, 90*IN_MILLISECONDS);
            }

            void HandleDummyTick(AuraEffect const* aurEff)
            {
                GetTarget()->CastSpell((Unit*)NULL, aurEff->GetAmount(), true);
            }

            void HandleUpdatePeriodic(AuraEffect* aurEff)
            {
                aurEff->CalculatePeriodic(GetCaster());
            }

            void Register()
            {
                DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY);
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::HandleDummyTick, EFFECT_0, SPELL_AURA_DUMMY);
                OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::HandleUpdatePeriodic, EFFECT_0, SPELL_AURA_DUMMY);
            }
        };

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

enum ForsakenSpells
{
    SPELL_FORSAKEN_SKILL_SWORD          = 7038,
    SPELL_FORSAKEN_SKILL_SHADOW         = 7053
};

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

        class spell_shadowfang_keep_forsaken_skills_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_shadowfang_keep_forsaken_skills_AuraScript);

            bool Load()
            {
                _forsakenSpell = 0;
                return true;
            }

            void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
            {
                _forsakenSpell = urand(SPELL_FORSAKEN_SKILL_SWORD, SPELL_FORSAKEN_SKILL_SHADOW);
                if (_forsakenSpell == SPELL_FORSAKEN_SKILL_SHADOW - 1)
                    ++_forsakenSpell;
                GetUnitOwner()->CastSpell(GetUnitOwner(), _forsakenSpell, true);
            }

            void HandleDummyTick(AuraEffect const* aurEff)
            {
                PreventDefaultAction();
                GetUnitOwner()->RemoveAurasDueToSpell(_forsakenSpell);
                _forsakenSpell = urand(SPELL_FORSAKEN_SKILL_SWORD, SPELL_FORSAKEN_SKILL_SHADOW);
                if (_forsakenSpell == SPELL_FORSAKEN_SKILL_SHADOW - 1)
                    ++_forsakenSpell;
                GetUnitOwner()->CastSpell(GetUnitOwner(), _forsakenSpell, true);
            }

            void Register()
            {
                OnEffectApply += AuraEffectApplyFn(spell_shadowfang_keep_forsaken_skills_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadowfang_keep_forsaken_skills_AuraScript::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
            }

        private:
            uint32 _forsakenSpell;
        };

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

void AddSC_instance_shadowfang_keep()
{
    new instance_shadowfang_keep();
    new spell_shadowfang_keep_haunting_spirits();
    new spell_shadowfang_keep_forsaken_skills();
}
