#include "enemies.h"

#include "constants.h"
#include "dragon.h"
#include "dwarf.h"
#include "elf.h"
#include "halfling.h"
#include "human.h"
#include "merchant.h"
#include "orc.h"
#include "viking.h"
#include "swordsman.h"
#include "leprechaun.h"
#include "witch.h"
#include "hacker.h"
#include "baby_dragon.h"

std::unique_ptr<enemy_base> new_dragon(RNG *rng, const position &pos,
                                       const position &fallback,
                                       const feature enabled_features,
                                       int which_room, const position &guards) {
        if (pos != POS_NIL)
                return std::make_unique<dragon>(rng, enabled_features,
                                                pos, which_room, guards);
        else
                return std::make_unique<dragon>(rng, enabled_features,
                                                fallback, which_room, guards);
}

const int EXCNT = 12;
const race EXCHOICES[EXCNT] = {
        HUMAN, DWARF, HALFLING, ELF, ORC, MERCHANT,
        VIKING, SWORDSMAN, LEPRECHAUN, WITCH, HACKER, BABY_DRAGON
};
const int CNT = 18;
const race CHOICES[CNT] = {
        HUMAN, HUMAN, HUMAN, HUMAN,
        DWARF, DWARF, DWARF,
        HALFLING, HALFLING, HALFLING, HALFLING, HALFLING,
        ELF, ELF,
        ORC, ORC,
        MERCHANT, MERCHANT
};

enum race get_extra_race(RNG *rng) {
        return EXCHOICES[rng->rand_under(EXCNT)];
}

enum race get_normal_race(RNG *rng) {
        return CHOICES[rng->rand_under(CNT)];
}

std::unique_ptr<enemy_base> new_enemy(RNG *rng, const position &pos,
                                      const feature enabled_features,
                                      int which_room) {
        enum race r;

        if (enabled_features & FEATURE_EXTRA_STUFF)
                r = get_extra_race(rng);
        else
                r = get_normal_race(rng);

        return new_enemy(r, pos, enabled_features, which_room, rng);
}

std::unique_ptr<enemy_base> new_enemy(const race &race, const position &pos,
                                      const feature enabled_features,
                                      int which_room, RNG *rng, const position &guards) {
        using std::make_unique;

        switch (race) {
        case DWARF:
                return make_unique<dwarf>(rng, enabled_features,
                                          pos, which_room);

        case HUMAN:
                return make_unique<human>(rng, enabled_features,
                                          pos, which_room);

        case ELF:
                return make_unique<elf>(rng, enabled_features,
                                        pos, which_room);

        case ORC:
                return make_unique<orc>(rng, enabled_features,
                                        pos, which_room);

        case MERCHANT:
                return make_unique<merchant>(rng, enabled_features,
                                             pos, which_room);

        case HALFLING:
                return make_unique<halfling>(rng, enabled_features,
                                             pos, which_room);

        case VIKING:
                return make_unique<viking>(rng, enabled_features,
                                           pos, which_room);

        case SWORDSMAN:
                return make_unique<swordsman>(rng, enabled_features,
                                              pos, which_room);

        case LEPRECHAUN:
                return make_unique<leprechaun>(rng, enabled_features,
                                               pos, which_room);

        case WITCH:
                return make_unique<witch>(rng, enabled_features,
                                          pos, which_room);

        case HACKER:
                return make_unique<hacker>(rng, enabled_features,
                                           pos, which_room);

        case BABY_DRAGON:
                return make_unique<baby_dragon>(rng, enabled_features,
                                                pos, which_room);

        case DRAGON:
                return make_unique<dragon>(rng, enabled_features,
                                           pos, which_room, guards);

        default:
                break;
        }

        return nullptr;
}
