/* 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 <iosfwd>
#include <stddef.h>
#include <string>

#if !defined(CMAKE_BUILD_WITH_CMAKE)
#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
{
  typedef void (cmArchiveWrite::*safe_bool)();
  void safe_bool_true() {}
public:
  /** Compression type.  */
  enum Compress
  {
    CompressNone,
    CompressCompress,
    CompressGZip,
    CompressBZip2,
    CompressLZMA,
    CompressXZ
  };

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

  ~cmArchiveWrite();

  /**
   * 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.  */
  operator safe_bool() const
  {
    return this->Okay() ? &cmArchiveWrite::safe_bool_true : nullptr;
  }

  /** 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 = "";
  }

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
