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

#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 this->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", int compressionLevel = 0,
                 int numThreads = 1);

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

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 = false;
  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;
};
