/* 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
