/**
 * @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 Adds a resource element to the list.
 * @param resource_type A type of resource.
 * @param id Id of the element to add.
 * @param description Description the element to add.
 * @return @c true if the element was added, @c false if an element with
 * this id already exists.
 */
bool QuestResources::add(
    ResourceType resource_type,
    const QString& id,
    const QString& description
) {

  if (!resources.add(resource_type, id.toStdString(), description.toStdString())) {
    return false;
  }
  emit element_added(resource_type, id, description);
  return true;
}
/**
 * @brief Creates a resource model.
 * @param quest The quest.
 * @param resource_type Type of resources to show.
 * @param parent The parent object or nullptr.
 */
ResourceModel::ResourceModel(const Quest& quest, ResourceType resource_type, QObject* parent) :
  QStandardItemModel(parent),
  quest(quest),
  resource_type(resource_type),
  items(),
  icons(),
  directory_icon(":/images/icon_folder_open.png"),
  tileset_id() {

  QStringList ids = get_resources().get_elements(this->resource_type);
  for (const QString& id : ids) {
    add_element(id);
  }

  const QuestResources& resources = get_resources();
  connect(&resources, SIGNAL(element_added(ResourceType, QString, QString)),
          this, SLOT(element_added(ResourceType, QString, QString)));
  connect(&resources, SIGNAL(element_removed(ResourceType, QString)),
          this, SLOT(element_removed(ResourceType, QString)));
  connect(&resources, SIGNAL(element_renamed(ResourceType, QString, QString)),
          this, SLOT(element_renamed(ResourceType, QString, QString)));
  connect(&resources, SIGNAL(element_description_changed(ResourceType, QString, QString)),
          this, SLOT(element_description_changed(ResourceType, QString, QString)));
}