#ifndef INOTEBOOKBACKEND_H
#define INOTEBOOKBACKEND_H

#include <QObject>

#include <utils/pathutils.h>

class QByteArray;
class QJsonObject;

namespace vnotex {
// Abstract class for notebook backend, which is responsible for file access
// and synchronization.
class INotebookBackend : public QObject {
  Q_OBJECT
public:
  INotebookBackend(const QString &p_rootPath, QObject *p_parent = nullptr)
      : QObject(p_parent), m_rootPath(PathUtils::absolutePath(p_rootPath)) {}

  virtual ~INotebookBackend() {}

  virtual QString getName() const = 0;

  virtual QString getDisplayName() const = 0;

  virtual QString getDescription() const = 0;

  const QString &getRootPath() const { return m_rootPath; }

  void setRootPath(const QString &p_rootPath) { m_rootPath = p_rootPath; }

  // Whether @p_dirPath is an empty directory.
  virtual bool isEmptyDir(const QString &p_dirPath) const = 0;

  // Create the directory path @p_dirPath. Create all parent directories if necessary.
  virtual void makePath(const QString &p_dirPath) = 0;

  // Write @p_data to @p_filePath.
  virtual void writeFile(const QString &p_filePath, const QByteArray &p_data) = 0;

  // Write @p_text to @p_filePath.
  virtual void writeFile(const QString &p_filePath, const QString &p_text) = 0;

  // Write @p_jobj to @p_filePath.
  virtual void writeFile(const QString &p_filePath, const QJsonObject &p_jobj) = 0;

  // Read content from @p_filePath.
  virtual QString readTextFile(const QString &p_filePath) = 0;

  // Read file @p_filePath.
  virtual QByteArray readFile(const QString &p_filePath) = 0;

  QString getFullPath(const QString &p_path) const;

  QString getRelativePath(const QString &p_path) const;

  virtual bool exists(const QString &p_path) const = 0;

  virtual bool existsFile(const QString &p_path) const = 0;

  virtual bool existsDir(const QString &p_path) const = 0;

  virtual bool childExistsCaseInsensitive(const QString &p_dirPath,
                                          const QString &p_name) const = 0;

  virtual bool isFile(const QString &p_path) const = 0;

  virtual void renameFile(const QString &p_filePath, const QString &p_name) = 0;

  virtual void renameDir(const QString &p_dirPath, const QString &p_name) = 0;

  // Copy @p_filePath to @p_destPath.
  // @p_filePath could be outside notebook.
  virtual void copyFile(const QString &p_filePath, const QString &p_destPath,
                        bool p_move = false) = 0;

  // Delete @p_filePath from disk.
  virtual void removeFile(const QString &p_filePath) = 0;

  // Copy  @p_dirPath to as @p_destPath.
  virtual void copyDir(const QString &p_dirPath, const QString &p_destPath,
                       bool p_move = false) = 0;

  // Delete @p_dirPath from disk if it is empty.
  // Return false if it is not deleted due to non-empty.
  virtual bool removeDirIfEmpty(const QString &p_dirPath) = 0;

  virtual void removeDir(const QString &p_dirPath) = 0;

  virtual QString renameIfExistsCaseInsensitive(const QString &p_path) const = 0;

  // Add one file to backend.
  virtual void addFile(const QString &p_path) = 0;

  virtual void removeEmptyDir(const QString &p_dirPath) = 0;

protected:
  // Constrain @p_path within root path of the notebook.
  void constrainPath(const QString &p_path) const;

private:
  // Root path of the notebook.
  QString m_rootPath;
};
} // namespace vnotex

#endif // INOTEBOOKBACKEND_H
