#ifndef __LEVEL_H__
#define __LEVEL_H__

#include <string>
#include <memory>
#include <vector>
#include <utility>
#include "output.h"
#include "gold.h"
#include "enemies.h"
#include "enemy.h"
#include "potions.h"
#include "map.h"

enum race : int;

struct level_data {
        position pc_pos;
        std::vector<std::pair<race, position>> enemies;
        std::vector<std::pair<potion_type, position>> potions;
        gold_list gold_piles;
        std::string map_data;
        position stairs;
};

class level {
private:
        static const int MAX_POTION_CNT = 15;
        static const int MAX_ENEMIE_CNT = 30;
        static const int MIN_POTION_CNT = 10;
        static const int MIN_ENEMIE_CNT = 20;
        static const int GOLD_CNT       = 10;

        const feature enabled_features;
        game_map map;
        character *player;
        std::vector<std::unique_ptr<enemy_base>>pelist;
        std::vector<std::unique_ptr<potion>>pplist;
        enemy_list elist;
        potion_list plist;
        gold_list glist;
public:
        // randomly generate a map
        level(character *player, RNG *rng, const feature enabled_features);
        // read map from data
        level(const level_data &lvl_data, character *player, RNG *rng,
              const feature enabled_features);
        void print(output *out) const;

        bool is_available(const position &pos, bool is_player = false) const;
        bool is_available_all(const position &pos) const;

        int get_room(const position &pos) const;
        position_list get_available_around(const position &pos) const;
        position_list get_available_around_all(const position &pos) const;
        position get_up_stairs() const;
        position get_down_stairs() const;

        // you can delete the pointers to the stuff
        const enemy_list &get_elist();
        const potion_list &get_plist();
        gold_list &get_glist();

        void add_gold(gold g);

        void erase_enemy(character *ch);
        std::unique_ptr<potion> detach_potion(size_t idx);

        size_t what_is_at(const position &pos) const;
private:
        // every gen will delete the positions in tiles
        void gen_potions(RNG *rng, std::vector<position_list> &tiles);
        void gen_gold(RNG *rng, std::vector<position_list> &tiles);
        void gen_enemies(const level_data &lvl, RNG *rng,
                         std::vector<position_list> &tiles);

        position get_rand_pos(RNG *rng, std::vector<position_list> &tiles);
        gold_list dragon_hoard(const level_data &lvl);
        bool is_in_glist(gold &g, const gold_list &gl);
        void fill(const level_data &lvl, std::vector<position_list> &tiles, RNG *rng);
};

#endif
