/*
 * CS 246 Final Project
 * File: map.h
 * Purpose: handles all characters
 */

#ifndef __CHARACTERS_H__
#define __CHARACTERS_H__
#include <vector>
#include <string>
#include <memory>
#include "constants.h"
#include "position.h"
#include "layer.h"
#include "objects.h"
#include "rng.h"
// #include "inventory.h" // Reserved for later

class character; // forward declaration
extern RNG rng;

// Note: player should not be in the character list
class character_list final: public layer {
private:
        std::vector<std::unique_ptr<character>> characters;
public:
        character_list();
        void print() const;
        void print(display &display) const;

        std::vector<std::unique_ptr<character>>::const_iterator begin() const;
        std::vector<std::unique_ptr<character>>::const_iterator end() const;
};

class character {
public:
        character(const race &nrace); // fills out the starting stats

        ~character(); // placeholder

        // usually I wouldn't do this but considering that the map has
        //  a super small size an O(n) solution is acceptable
        // IMPORTANT: available_positions do NOT have characters in them
        direction_list moveable(const position_list &available_positions) const;
        virtual result move(const direction dir,
                            const position_list &available_positions) = 0;
        virtual result attack(const direction dir,
                              const character_list &chlist) = 0;
        virtual result move_or_attack(const direction dir,
                                      const position_list &available_positions,
                                      const character_list &chlist) = 0;
        virtual result apply(direction &dir,
                             const potion_list &potions);
        virtual result get_hit(const enum race &race, const int atk,
                               const float hitrate) = 0;
        enum race get_race() const;
        position get_position() const;
        int get_HP() const;
        int get_ATK() const;
        int get_DEF() const;
        int get_gold() const;
        float get_hitrate() const;
        bool is_hostile() const;

        void set_position(const position &npos);
        void set_HP(const int nHP);
        void set_ATK(const int nATK);
        void set_DEF(const int nDEF);
        void set_gold(const int ngold);
        void set_hitrate(const float nhitrate);
        void set_hostile(const bool is_hostile);

        // if stat is hostile, positive to set it to hostile,
        //                     negative to set it to peaceful
        void apply_buff(const stat_name statn, const int amount);
        // void apply_buff(const stat_name statn, const float mul);
        // reserved for later
protected:
        const enum race race;

        int HP;
        int ATK;
        int DEF;

        position pos;

        int gold; // characters spawn with gold
        // inventory inventory; // Reserved

        float base_hitrate; // requires: between [0,1]

        bool hostile;
};

// requires: all elements of excluded are in sorted_positions
position_list remove_from_list(const position_list &sorted_positions,
                               position_list excluded);

#endif
