#include "characters.h"

#include <algorithm>

character::character(const enum race &nrace):
        race{nrace}, HP{STARTING_HP[race]},
        ATK{STARTING_ATK[race]}, DEF{STARTING_DEF[race]} {}

character::~character() {}

enum race character::get_race() const {
        return race;
}

position character::get_position() const {
        return pos;
}

int character::get_HP() const {
        return HP;
}

int character::get_ATK() const {
        return ATK;
}

int character::get_DEF() const {
        return DEF;
}

int character::get_gold() const {
        return gold;
}

float character::get_hitrate() const {
        return base_hitrate;
}

bool character::is_hostile() const {
        return hostile;
}

void character::set_position(const position &npos) {
        pos = npos;
}

void character::set_HP(const int nHP) {
        HP = nHP;
}

void character::set_ATK(const int nATK) {
        ATK = nATK;
}

void character::set_DEF(const int nDEF) {
        DEF = nDEF;
}

void character::set_gold(const int ngold) {
        gold = ngold;
}

void character::set_hitrate(const float nhitrate) {
        base_hitrate = nhitrate;
}

void character::set_hostile(const bool is_hostile) {
        hostile = is_hostile;
}

void character::apply_buff(const stat_name statn, const int amount) {
        switch (statn) {
        case stat_name::HP:
                HP += amount;
                break;

        case stat_name::ATK:
                ATK += amount;
                break;

        case stat_name::DEF:
                DEF += amount;
                break;

        case stat_name::hostile: {
                if (amount > 0)
                        hostile = true;
                else
                        hostile = false;

                break;
        }
        }
}

character_list::character_list():
        layer{layer_num::characters} {}

void character_list::print() const {
        // TODO: implement it using ncurses
}

void character_list::print(display &display) const {
        for (auto &ch : characters)
                display.print_position(ch->get_position(),
                                       CHARACTER_REP[ch->get_race()]);
}

std::vector<std::unique_ptr<character>>::const_iterator character_list::begin()
const {
        return characters.begin();
}

std::vector<std::unique_ptr<character>>::const_iterator character_list::end()
const {
        return characters.end();
}

direction_list character::moveable(const position_list &available_positions)
const {
        direction_list result;

        for (int i = 0; i < DIRECTION_CNT; ++i)
                if (find(available_positions, pos + MOVE[i])
                    != available_positions.size())
                        result.push_back((direction)i);

        return result;
}

result character::apply(direction &dir, const potion_list &potions) {
        // TODO: implement this after implementing potions
        return result::fine;
}

position_list remove_from_list(const position_list &sorted_positions,
                               position_list excluded) {
        std::sort(excluded.begin(), excluded.end());

        position_list result{sorted_positions.size() - excluded.size()};

        auto exc = excluded.begin();

        for (auto src : sorted_positions) {
                if (exc != excluded.end() && src == *exc)
                        ++exc;
                else
                        result.push_back(src);
        }

        return result;
}
