/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmArchiveWrite_h
#define cmArchiveWrite_h

#include "cmConfigure.h" // IWYU pragma: keep

#include <cstddef>
#include <iosfwd>
#include <string>

#if defined(CMAKE_BOOTSTRAP)
#  error "cmArchiveWrite not allowed during bootstrap build!"
#endif

template <typename T>
class cmArchiveWriteOptional
{
public:
  cmArchiveWriteOptional() { this->Clear(); }
  explicit cmArchiveWriteOptional(T val) { this->Set(val); }

  void Set(T val)
  {
    this->IsValueSet = true;
    this->Value = val;
  }
  void Clear() { this->IsValueSet = false; }
  bool IsSet() const { return this->IsValueSet; }
  T Get() const { return Value; }

private:
  T Value;
  bool IsValueSet;
};

/** \class cmArchiveWrite
 * \brief Wrapper around libarchive for writing.
 *
 */
class cmArchiveWrite
{
public:
  /** Compression type.  */
  enum Compress
  {
    CompressNone,
    CompressCompress,
    CompressGZip,
    CompressBZip2,
    CompressLZMA,
    CompressXZ,
    CompressZstd
  };

  /** Construct with output stream to which to write archive.  */
  cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
                 std::string const& format = "paxr");

  ~cmArchiveWrite();

  cmArchiveWrite(const cmArchiveWrite&) = delete;
  cmArchiveWrite& operator=(const cmArchiveWrite&) = delete;

  bool Open();

  /**
   * Add a path (file or directory) to the archive.  Directories are
   * added recursively.  The "path" must be readable on disk, either
   * full path or relative to current working directory.  The "skip"
   * value indicates how many leading bytes from the input path to
   * skip.  The remaining part of the input path is appended to the
   * "prefix" value to construct the final name in the archive.
   */
  bool Add(std::string path, size_t skip = 0, const char* prefix = nullptr,
           bool recursive = true);

  /** Returns true if there has been no error.  */
  explicit operator bool() const { return this->Okay(); }

  /** Returns true if there has been an error.  */
  bool operator!() const { return !this->Okay(); }

  /** Return the error string; empty if none.  */
  std::string GetError() const { return this->Error; }

  // TODO: More general callback instead of hard-coding calls to
  // std::cout.
  void SetVerbose(bool v) { this->Verbose = v; }

  void SetMTime(std::string const& t) { this->MTime = t; }

  //! Sets the permissions of the added files/folders
  void SetPermissions(int permissions_)
  {
    this->Permissions.Set(permissions_);
  }

  //! Clears permissions - default is used instead
  void ClearPermissions() { this->Permissions.Clear(); }

  //! Sets the permissions mask of files/folders
  //!
  //! The permissions will be copied from the existing file
  //! or folder. The mask will then be applied to unset
  //! some of them
  void SetPermissionsMask(int permissionsMask_)
  {
    this->PermissionsMask.Set(permissionsMask_);
  }

  //! Clears permissions mask - default is used instead
  void ClearPermissionsMask() { this->PermissionsMask.Clear(); }

  //! Sets UID and GID to be used in the tar file
  void SetUIDAndGID(int uid_, int gid_)
  {
    this->Uid.Set(uid_);
    this->Gid.Set(gid_);
  }

  //! Clears UID and GID to be used in the tar file - default is used instead
  void ClearUIDAndGID()
  {
    this->Uid.Clear();
    this->Gid.Clear();
  }

  //! Sets UNAME and GNAME to be used in the tar file
  void SetUNAMEAndGNAME(const std::string& uname_, const std::string& gname_)
  {
    this->Uname = uname_;
    this->Gname = gname_;
  }

  //! Clears UNAME and GNAME to be used in the tar file
  //! default is used instead
  void ClearUNAMEAndGNAME()
  {
    this->Uname = "";
    this->Gname = "";
  }

  //! Set an option on a filter;
  bool SetFilterOption(const char* module, const char* key, const char* value);

private:
  bool Okay() const { return this->Error.empty(); }
  bool AddPath(const char* path, size_t skip, const char* prefix,
               bool recursive = true);
  bool AddFile(const char* file, size_t skip, const char* prefix);
  bool AddData(const char* file, size_t size);

  struct Callback;
  friend struct Callback;

  class Entry;

  std::ostream& Stream;
  struct archive* Archive;
  struct archive* Disk;
  bool Verbose;
  std::string Format;
  std::string Error;
  std::string MTime;

  //! UID of the user in the tar file
  cmArchiveWriteOptional<int> Uid;

  //! GUID of the user in the tar file
  cmArchiveWriteOptional<int> Gid;

  //! UNAME/GNAME of the user (does not override UID/GID)
  //!@{
  std::string Uname;
  std::string Gname;
  //!@}

  //! Permissions on files/folders
  cmArchiveWriteOptional<int> Permissions;
  cmArchiveWriteOptional<int> PermissionsMask;
};

#endif
