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

#include "cmsys/FStream.hxx"
#include <sstream>
#include <stdio.h>
#include <string>

#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
#include "cm_sys_stat.h"

cmCPackSTGZGenerator::cmCPackSTGZGenerator()
{
}

cmCPackSTGZGenerator::~cmCPackSTGZGenerator()
{
}

int cmCPackSTGZGenerator::InitializeInternal()
{
  this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "0");

  std::string inFile = this->FindTemplate("CPack.STGZ_Header.sh.in");
  if (inFile.empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find template file: " << inFile << std::endl);
    return 0;
  }
  this->SetOptionIfNotSet("CPACK_STGZ_HEADER_FILE", inFile.c_str());
  this->SetOptionIfNotSet("CPACK_AT_SIGN", "@");

  return this->Superclass::InitializeInternal();
}

int cmCPackSTGZGenerator::PackageFiles()
{
  bool retval = true;
  if (!this->Superclass::PackageFiles()) {
    return 0;
  }

  /* TGZ generator (our Superclass) may
   * have generated several packages (component packaging)
   * so we must iterate over generated packages.
   */
  for (std::string const& pfn : packageFileNames) {
    retval &= cmSystemTools::SetPermissions(pfn.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
                                            S_IREAD | S_IWRITE | S_IEXEC
#else
                                            S_IRUSR | S_IWUSR | S_IXUSR |
                                              S_IRGRP | S_IWGRP | S_IXGRP |
                                              S_IROTH | S_IWOTH | S_IXOTH
#endif
                                            );
  }
  return retval;
}

int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
{
  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Writing header" << std::endl);
  std::ostringstream str;
  int counter = 0;

  std::string inLicFile = this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
  std::string line;
  cmsys::ifstream ilfs(inLicFile.c_str());
  std::string licenseText;
  while (cmSystemTools::GetLineFromStream(ilfs, line)) {
    licenseText += line + "\n";
  }
  this->SetOptionIfNotSet("CPACK_RESOURCE_FILE_LICENSE_CONTENT",
                          licenseText.c_str());

  const char headerLengthTag[] = "###CPACK_HEADER_LENGTH###";

  // Create the header
  std::string inFile = this->GetOption("CPACK_STGZ_HEADER_FILE");
  cmsys::ifstream ifs(inFile.c_str());
  std::string packageHeaderText;
  while (cmSystemTools::GetLineFromStream(ifs, line)) {
    packageHeaderText += line + "\n";
  }

  // Configure in the values
  std::string res;
  this->ConfigureString(packageHeaderText, res);

  // Count the lines
  const char* ptr = res.c_str();
  while (*ptr) {
    if (*ptr == '\n') {
      counter++;
    }
    ++ptr;
  }
  counter++;
  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Number of lines: " << counter
                                                           << std::endl);
  char buffer[1024];
  sprintf(buffer, "%d", counter);
  cmSystemTools::ReplaceString(res, headerLengthTag, buffer);

  // Write in file
  *os << res;
  return this->Superclass::GenerateHeader(os);
}
