/**
 * @brief Creates a quest files model.
 * @param parent Path of the quest to represent.
 */
QuestFilesModel::QuestFilesModel(Quest& quest):
  QSortFilterProxyModel(nullptr),
  quest(quest),
  source_model(new QFileSystemModel) {

  // Watch changes on the filesystem.
  source_model->setRootPath(quest.get_data_path());  // Only watch changes in the data directory.
  source_model->setReadOnly(false);
  setSourceModel(source_model);

  // Watch changes in resources.
  connect(&quest.get_resources(), SIGNAL(element_added(ResourceType, QString, QString)),
          this, SLOT(resource_element_added(ResourceType, QString, QString)));
  connect(&quest.get_resources(), SIGNAL(element_removed(ResourceType, QString)),
          this, SLOT(resource_element_removed(ResourceType, QString)));
  connect(&quest.get_resources(), SIGNAL(element_renamed(ResourceType, QString, QString)),
          this, SLOT(resource_element_renamed(ResourceType, QString, QString)));
  connect(&quest.get_resources(), SIGNAL(element_description_changed(ResourceType, QString, QString)),
          this, SLOT(resource_element_description_changed(ResourceType, QString, QString)));

  // This model adds extra items for files missing on the filesystem.
  // To ensure we have an extra item if and only if the file is missing,
  // we need to watch files creations and destructions.
  connect(source_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
          SLOT(source_model_rows_inserted(QModelIndex, int, int)));
  connect(source_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
          SLOT(source_model_rows_about_to_be_removed(QModelIndex, int, int)));
}
/**
 * @brief Creates a sprite model.
 * @param quest The quest.
 * @param sprite_id Id of the sprite to manage.
 * @param parent The parent object or nullptr.
 * @throws EditorException If the file could not be opened.
 */
SpriteModel::SpriteModel(
    Quest& quest,
    const QString& sprite_id,
    QObject* parent) :
  QAbstractItemModel(parent),
  quest(quest),
  sprite_id(sprite_id),
  selection_model(this) {

  // Load the sprite data file.
  QString path = quest.get_sprite_path(sprite_id);

  if (!sprite.import_from_file(path.toStdString())) {
    throw EditorException(tr("Cannot open sprite '%1'").arg(path));
  }

  // Build the index map of animations.
  build_index_map();

  // Create animations and directions models.
  for (const auto& kvp : names_to_indexes) {
    const QString& animation_name = kvp.first;
    AnimationModel animation(animation_name);
    int num_dir = get_animation(animation_name).get_num_directions();
    for (int nb = 0; nb < num_dir; nb++) {
      animation.directions.append(DirectionModel(animation_name, nb));
    }
    animations.append(animation);
  }

  // use the first tileset of the quest
  QStringList tilesets =
      quest.get_resources().get_elements(ResourceType::TILESET);
  if (tilesets.size() > 0) {
    tileset_id = tilesets[0];
  }
}