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

#include <vector>

#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"

cmCPackPKGGenerator::cmCPackPKGGenerator()
{
  this->componentPackageMethod = ONE_PACKAGE;
}

cmCPackPKGGenerator::~cmCPackPKGGenerator() = default;

bool cmCPackPKGGenerator::SupportsComponentInstallation() const
{
  return true;
}

int cmCPackPKGGenerator::InitializeInternal()
{
  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                "cmCPackPKGGenerator::Initialize()" << std::endl);

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

std::string cmCPackPKGGenerator::GetPackageName(
  const cmCPackComponent& component)
{
  if (component.ArchiveFile.empty()) {
    std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
    packagesDir += ".dummy";
    std::ostringstream out;
    out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
        << component.Name << ".pkg";
    return out.str();
  }

  return component.ArchiveFile + ".pkg";
}

void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
{
  std::string distributionTemplate =
    this->FindTemplate("CPack.distribution.dist.in");
  if (distributionTemplate.empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find input file: " << distributionTemplate
                                             << std::endl);
    return;
  }

  std::string distributionFile = metapackageFile;
  distributionFile += "/Contents/distribution.dist";

  // Create the choice outline, which provides a tree-based view of
  // the components in their groups.
  std::ostringstream choiceOut;
  cmXMLWriter xout(choiceOut, 1);
  xout.StartElement("choices-outline");

  // Emit the outline for the groups
  std::map<std::string, cmCPackComponentGroup>::iterator groupIt;
  for (groupIt = this->ComponentGroups.begin();
       groupIt != this->ComponentGroups.end(); ++groupIt) {
    if (groupIt->second.ParentGroup == nullptr) {
      CreateChoiceOutline(groupIt->second, xout);
    }
  }

  // Emit the outline for the non-grouped components
  std::map<std::string, cmCPackComponent>::iterator compIt;
  for (compIt = this->Components.begin(); compIt != this->Components.end();
       ++compIt) {
    if (!compIt->second.Group) {
      xout.StartElement("line");
      xout.Attribute("choice", compIt->first + "Choice");
      xout.Content(""); // Avoid self-closing tag.
      xout.EndElement();
    }
  }
  if (!this->PostFlightComponent.Name.empty()) {
    xout.StartElement("line");
    xout.Attribute("choice", PostFlightComponent.Name + "Choice");
    xout.Content(""); // Avoid self-closing tag.
    xout.EndElement();
  }
  xout.EndElement(); // choices-outline>

  // Create the actual choices
  for (groupIt = this->ComponentGroups.begin();
       groupIt != this->ComponentGroups.end(); ++groupIt) {
    CreateChoice(groupIt->second, xout);
  }
  for (compIt = this->Components.begin(); compIt != this->Components.end();
       ++compIt) {
    CreateChoice(compIt->second, xout);
  }

  if (!this->PostFlightComponent.Name.empty()) {
    CreateChoice(PostFlightComponent, xout);
  }

  this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str());

  // Create the distribution.dist file in the metapackage to turn it
  // into a distribution package.
  this->ConfigureFile(distributionTemplate.c_str(), distributionFile.c_str());
}

void cmCPackPKGGenerator::CreateChoiceOutline(
  const cmCPackComponentGroup& group, cmXMLWriter& xout)
{
  xout.StartElement("line");
  xout.Attribute("choice", group.Name + "Choice");
  std::vector<cmCPackComponentGroup*>::const_iterator groupIt;
  for (groupIt = group.Subgroups.begin(); groupIt != group.Subgroups.end();
       ++groupIt) {
    CreateChoiceOutline(**groupIt, xout);
  }

  std::vector<cmCPackComponent*>::const_iterator compIt;
  for (compIt = group.Components.begin(); compIt != group.Components.end();
       ++compIt) {
    xout.StartElement("line");
    xout.Attribute("choice", (*compIt)->Name + "Choice");
    xout.Content(""); // Avoid self-closing tag.
    xout.EndElement();
  }
  xout.EndElement();
}

void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group,
                                       cmXMLWriter& xout)
{
  xout.StartElement("choice");
  xout.Attribute("id", group.Name + "Choice");
  xout.Attribute("title", group.DisplayName);
  xout.Attribute("start_selected", "true");
  xout.Attribute("start_enabled", "true");
  xout.Attribute("start_visible", "true");
  if (!group.Description.empty()) {
    xout.Attribute("description", group.Description);
  }
  xout.EndElement();
}

void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
                                       cmXMLWriter& xout)
{
  std::string packageId = "com.";
  packageId += this->GetOption("CPACK_PACKAGE_VENDOR");
  packageId += '.';
  packageId += this->GetOption("CPACK_PACKAGE_NAME");
  packageId += '.';
  packageId += component.Name;

  xout.StartElement("choice");
  xout.Attribute("id", component.Name + "Choice");
  xout.Attribute("title", component.DisplayName);
  xout.Attribute(
    "start_selected",
    component.IsDisabledByDefault && !component.IsRequired ? "false" : "true");
  xout.Attribute("start_enabled", component.IsRequired ? "false" : "true");
  xout.Attribute("start_visible", component.IsHidden ? "false" : "true");
  if (!component.Description.empty()) {
    xout.Attribute("description", component.Description);
  }
  if (!component.Dependencies.empty() ||
      !component.ReverseDependencies.empty()) {
    // The "selected" expression is evaluated each time any choice is
    // selected, for all choices *except* the one that the user
    // selected. A component is marked selected if it has been
    // selected (my.choice.selected in Javascript) and all of the
    // components it depends on have been selected (transitively) or
    // if any of the components that depend on it have been selected
    // (transitively). Assume that we have components A, B, C, D, and
    // E, where each component depends on the previous component (B
    // depends on A, C depends on B, D depends on C, and E depends on
    // D). The expression we build for the component C will be
    //   my.choice.selected && B && A || D || E
    // This way, selecting C will automatically select everything it depends
    // on (B and A), while selecting something that depends on C--either D
    // or E--will automatically cause C to get selected.
    std::ostringstream selected("my.choice.selected", std::ios_base::ate);
    std::set<const cmCPackComponent*> visited;
    AddDependencyAttributes(component, visited, selected);
    visited.clear();
    AddReverseDependencyAttributes(component, visited, selected);
    xout.Attribute("selected", selected.str());
  }
  xout.StartElement("pkg-ref");
  xout.Attribute("id", packageId);
  xout.EndElement(); // pkg-ref
  xout.EndElement(); // choice

  // Create a description of the package associated with this
  // component.
  std::string relativePackageLocation = "Contents/Packages/";
  relativePackageLocation += this->GetPackageName(component);

  // Determine the installed size of the package.
  std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
  dirName += '/';
  dirName += component.Name;
  dirName += this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
  unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName);

  xout.StartElement("pkg-ref");
  xout.Attribute("id", packageId);
  xout.Attribute("version", this->GetOption("CPACK_PACKAGE_VERSION"));
  xout.Attribute("installKBytes", installedSize);
  xout.Attribute("auth", "Admin");
  xout.Attribute("onConclusion", "None");
  if (component.IsDownloaded) {
    xout.Content(this->GetOption("CPACK_DOWNLOAD_SITE"));
    xout.Content(this->GetPackageName(component));
  } else {
    xout.Content("file:./");
    xout.Content(cmSystemTools::EncodeURL(relativePackageLocation,
                                          /*escapeSlashes=*/false));
  }
  xout.EndElement(); // pkg-ref
}

void cmCPackPKGGenerator::AddDependencyAttributes(
  const cmCPackComponent& component,
  std::set<const cmCPackComponent*>& visited, std::ostringstream& out)
{
  if (visited.find(&component) != visited.end()) {
    return;
  }
  visited.insert(&component);

  std::vector<cmCPackComponent*>::const_iterator dependIt;
  for (dependIt = component.Dependencies.begin();
       dependIt != component.Dependencies.end(); ++dependIt) {
    out << " && choices['" << (*dependIt)->Name << "Choice'].selected";
    AddDependencyAttributes(**dependIt, visited, out);
  }
}

void cmCPackPKGGenerator::AddReverseDependencyAttributes(
  const cmCPackComponent& component,
  std::set<const cmCPackComponent*>& visited, std::ostringstream& out)
{
  if (visited.find(&component) != visited.end()) {
    return;
  }
  visited.insert(&component);

  std::vector<cmCPackComponent*>::const_iterator dependIt;
  for (dependIt = component.ReverseDependencies.begin();
       dependIt != component.ReverseDependencies.end(); ++dependIt) {
    out << " || choices['" << (*dependIt)->Name << "Choice'].selected";
    AddReverseDependencyAttributes(**dependIt, visited, out);
  }
}

bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
                                                 const std::string& dirName)
{
  std::string uname = cmSystemTools::UpperCase(name);
  std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
  const char* inFileName = this->GetOption(cpackVar);
  if (!inFileName) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPack option: " << cpackVar.c_str()
                                   << " not specified. It should point to "
                                   << (!name.empty() ? name : "<empty>")
                                   << ".rtf, " << name << ".html, or " << name
                                   << ".txt file" << std::endl);
    return false;
  }
  if (!cmSystemTools::FileExists(inFileName)) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find " << (!name.empty() ? name : "<empty>")
                                 << " resource file: " << inFileName
                                 << std::endl);
    return false;
  }
  std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName);
  if (ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt") {
    cmCPackLogger(
      cmCPackLog::LOG_ERROR,
      "Bad file extension specified: "
        << ext
        << ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
        << std::endl);
    return false;
  }

  std::string destFileName = dirName;
  destFileName += '/';
  destFileName += name + ext;

  // Set this so that distribution.dist gets the right name (without
  // the path).
  this->SetOption("CPACK_RESOURCE_FILE_" + uname + "_NOPATH",
                  (name + ext).c_str());

  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "Configure file: " << (inFileName ? inFileName : "(NULL)")
                                   << " to " << destFileName << std::endl);
  this->ConfigureFile(inFileName, destFileName.c_str());
  return true;
}

bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
                                                const char* outName)
{
  if (!outName) {
    outName = name.c_str();
  }

  std::string inFName = "CPack.";
  inFName += name;
  inFName += ".in";
  std::string inFileName = this->FindTemplate(inFName.c_str());
  if (inFileName.empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find input file: " << inFName << std::endl);
    return false;
  }

  std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
  destFileName += "/";
  destFileName += outName;

  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "Configure file: " << inFileName << " to " << destFileName
                                   << std::endl);
  this->ConfigureFile(inFileName.c_str(), destFileName.c_str());
  return true;
}

int cmCPackPKGGenerator::CopyInstallScript(const std::string& resdir,
                                           const std::string& script,
                                           const std::string& name)
{
  std::string dst = resdir;
  dst += "/";
  dst += name;
  cmSystemTools::CopyFileAlways(script, dst);
  cmSystemTools::SetPermissions(dst.c_str(), 0777);
  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "copy script : " << script << "\ninto " << dst << std::endl);

  return 1;
}
