#pragma once

#include <map>
#include <vector>
#include <string>
#include <functional>

class GameDatabase {
 public:
  GameDatabase() = default;

  /// вставляет в базу объект с именем [name] и позицией [x, y]
  /// если объект с таким id в базе уже есть, заменяет его новым
  void Insert(ObjectId id, string name, size_t x, size_t y) {
    GameObject in = {id, name, x, y};
    db[id] = in;
  }

  /// удаляет элемент по id
  /// если такого элемента нет, ничего не делает
  void Remove(ObjectId id) {
    auto it = db.find(id);
    if (it != db.end()) {
      db.erase(it);
    }
  }

  /// возвращает вектор объектов c именем [name]
  /// сортировка по убыванию id
  vector<GameObject> DataByName(string name) const {
    vector<GameObject> v;
    for (auto it = db.begin(); it != db.end(); ++it) {
      if ((it->second).name == name) {
        v.push_back(it->second);
      }
    }
    return v;
  }

  /// возвращает вектор объектов, находящихся в позиции [x, y]
  /// сортировка по убыванию id
  vector<GameObject> DataByPosition(size_t x, size_t y) const {
    vector<GameObject> v;
    for (auto it = db.begin(); it != db.end(); ++it) {
      if ((it->second).x == x && (it->second).y == y) {
        v.push_back(it->second);
      }
    }
    return v;
  }

  /// возвращает вектор всех объектов из базы
  /// сортировка по убыванию id
  vector<GameObject> Data() const {
    vector<GameObject> v;
    for (auto it = db.begin(); it != db.end(); ++it) {
      v.push_back(it->second);
    }
    return v;
  }

 private:
  std::map<int, GameObject, std::greater<ObjectId>> db;
};