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

#include <algorithm>
#include <cctype>
#include <map>
#include <ostream>
#include <utility>
#include <vector>

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

cmCPackRPMGenerator::cmCPackRPMGenerator() = default;

cmCPackRPMGenerator::~cmCPackRPMGenerator() = default;

int cmCPackRPMGenerator::InitializeInternal()
{
  this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
  if (cmIsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
    this->SetOption("CPACK_SET_DESTDIR", "I_ON");
  }
  /* Replace space in CPACK_PACKAGE_NAME in order to avoid
   * rpmbuild scream on unwanted space in filename issue
   * Moreover RPM file do not usually embed space in filename
   */
  if (this->GetOption("CPACK_PACKAGE_NAME")) {
    std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
    std::replace(packageName.begin(), packageName.end(), ' ', '-');
    this->SetOption("CPACK_PACKAGE_NAME", packageName.c_str());
  }
  /* same for CPACK_PACKAGE_FILE_NAME */
  if (this->GetOption("CPACK_PACKAGE_FILE_NAME")) {
    std::string packageName = this->GetOption("CPACK_PACKAGE_FILE_NAME");
    std::replace(packageName.begin(), packageName.end(), ' ', '-');
    this->SetOption("CPACK_PACKAGE_FILE_NAME", packageName.c_str());
  }
  return this->Superclass::InitializeInternal();
}

void cmCPackRPMGenerator::AddGeneratedPackageNames()
{
  // add the generated packages to package file names list
  std::string fileNames(this->GetOption("GEN_CPACK_OUTPUT_FILES"));
  const char sep = ';';
  std::string::size_type pos1 = 0;
  std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
  while (pos2 != std::string::npos) {
    packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
    pos1 = pos2 + 1;
    pos2 = fileNames.find(sep, pos1 + 1);
  }
  packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
}

int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
                                        std::string const& packageName)
{
  int retval = 1;
  // Begin the archive for this pack
  std::string localToplevel(initialToplevel);
  std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
  std::string outputFileName(
    GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
                                packageName, true) +
    this->GetOutputExtension());

  localToplevel += "/" + packageName;
  /* replace the TEMP DIRECTORY with the component one */
  this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
  packageFileName += "/" + outputFileName;
  /* replace proposed CPACK_OUTPUT_FILE_NAME */
  this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
  /* replace the TEMPORARY package file name */
  this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
                  packageFileName.c_str());
  // Tell CPackRPM.cmake the name of the component NAME.
  this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str());
  // Tell CPackRPM.cmake the path where the component is.
  std::string component_path = cmStrCat('/', packageName);
  this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
                  component_path.c_str());
  if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Error while execution CPackRPM.cmake" << std::endl);
    retval = 0;
  }

  return retval;
}

int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
{
  int retval = 1;
  /* Reset package file name list it will be populated during the
   * component packaging run*/
  packageFileNames.clear();
  std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));

  const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");

  if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") &&
      !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) {
    // check if we need to set CPACK_RPM_DEBUGINFO_PACKAGE because non of
    // the components is setting per component debuginfo package variable
    bool shouldSet = true;

    if (ignoreGroup) {
      std::map<std::string, cmCPackComponent>::iterator compIt;
      for (compIt = this->Components.begin(); compIt != this->Components.end();
           ++compIt) {
        std::string component(compIt->first);
        std::transform(component.begin(), component.end(), component.begin(),
                       ::toupper);

        if (this->IsOn("CPACK_RPM_" + compIt->first + "_DEBUGINFO_PACKAGE") ||
            this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
          shouldSet = false;
          break;
        }
      }
    } else {
      std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
      for (compGIt = this->ComponentGroups.begin();
           compGIt != this->ComponentGroups.end(); ++compGIt) {
        std::string component(compGIt->first);
        std::transform(component.begin(), component.end(), component.begin(),
                       ::toupper);

        if (this->IsOn("CPACK_RPM_" + compGIt->first + "_DEBUGINFO_PACKAGE") ||
            this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
          shouldSet = false;
          break;
        }
      }

      if (shouldSet) {
        std::map<std::string, cmCPackComponent>::iterator compIt;
        for (compIt = this->Components.begin();
             compIt != this->Components.end(); ++compIt) {
          // Does the component belong to a group?
          if (compIt->second.Group == nullptr) {
            std::string component(compIt->first);
            std::transform(component.begin(), component.end(),
                           component.begin(), ::toupper);

            if (this->IsOn("CPACK_RPM_" + compIt->first +
                           "_DEBUGINFO_PACKAGE") ||
                this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
              shouldSet = false;
              break;
            }
          }
        }
      }
    }

    if (shouldSet) {
      cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                    "Setting "
                      << "CPACK_RPM_DEBUGINFO_PACKAGE because "
                      << "CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is set but "
                      << " none of the "
                      << "CPACK_RPM_<component>_DEBUGINFO_PACKAGE variables "
                      << "are set." << std::endl);
      this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON");
    }
  }

  if (mainComponent) {
    if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
      this->SetOption("GENERATE_SPEC_PARTS", "ON");
    }

    std::string mainComponentUpper(mainComponent);
    std::transform(mainComponentUpper.begin(), mainComponentUpper.end(),
                   mainComponentUpper.begin(), ::toupper);

    // The default behavior is to have one package by component group
    // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
    if (!ignoreGroup) {
      auto mainCompGIt = this->ComponentGroups.end();

      std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
      for (compGIt = this->ComponentGroups.begin();
           compGIt != this->ComponentGroups.end(); ++compGIt) {
        std::string component(compGIt->first);
        std::transform(component.begin(), component.end(), component.begin(),
                       ::toupper);

        if (mainComponentUpper == component) {
          // main component will be handled last
          mainCompGIt = compGIt;
          continue;
        }

        cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                      "Packaging component group: " << compGIt->first
                                                    << std::endl);
        retval &= PackageOnePack(initialTopLevel, compGIt->first);
      }
      // Handle Orphan components (components not belonging to any groups)
      auto mainCompIt = this->Components.end();
      std::map<std::string, cmCPackComponent>::iterator compIt;
      for (compIt = this->Components.begin(); compIt != this->Components.end();
           ++compIt) {
        // Does the component belong to a group?
        if (compIt->second.Group == nullptr) {
          std::string component(compIt->first);
          std::transform(component.begin(), component.end(), component.begin(),
                         ::toupper);

          if (mainComponentUpper == component) {
            // main component will be handled last
            mainCompIt = compIt;
            continue;
          }

          cmCPackLogger(
            cmCPackLog::LOG_VERBOSE,
            "Component <"
              << compIt->second.Name
              << "> does not belong to any group, package it separately."
              << std::endl);
          retval &= PackageOnePack(initialTopLevel, compIt->first);
        }
      }

      if (retval) {
        this->SetOption("GENERATE_SPEC_PARTS", "OFF");

        if (mainCompGIt != this->ComponentGroups.end()) {
          retval &= PackageOnePack(initialTopLevel, mainCompGIt->first);
        } else if (mainCompIt != this->Components.end()) {
          retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
        } else {
          cmCPackLogger(cmCPackLog::LOG_ERROR,
                        "CPACK_RPM_MAIN_COMPONENT set"
                          << " to non existing component.\n");
          retval = 0;
        }
      }
    }
    // CPACK_COMPONENTS_IGNORE_GROUPS is set
    // We build 1 package per component
    else {
      auto mainCompIt = this->Components.end();

      std::map<std::string, cmCPackComponent>::iterator compIt;
      for (compIt = this->Components.begin(); compIt != this->Components.end();
           ++compIt) {
        std::string component(compIt->first);
        std::transform(component.begin(), component.end(), component.begin(),
                       ::toupper);

        if (mainComponentUpper == component) {
          // main component will be handled last
          mainCompIt = compIt;
          continue;
        }

        retval &= PackageOnePack(initialTopLevel, compIt->first);
      }

      if (retval) {
        this->SetOption("GENERATE_SPEC_PARTS", "OFF");

        if (mainCompIt != this->Components.end()) {
          retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
        } else {
          cmCPackLogger(cmCPackLog::LOG_ERROR,
                        "CPACK_RPM_MAIN_COMPONENT set"
                          << " to non existing component.\n");
          retval = 0;
        }
      }
    }
  } else if (!this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") ||
             this->Components.size() == 1) {
    // The default behavior is to have one package by component group
    // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
    if (!ignoreGroup) {
      std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
      for (compGIt = this->ComponentGroups.begin();
           compGIt != this->ComponentGroups.end(); ++compGIt) {
        cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                      "Packaging component group: " << compGIt->first
                                                    << std::endl);
        retval &= PackageOnePack(initialTopLevel, compGIt->first);
      }
      // Handle Orphan components (components not belonging to any groups)
      std::map<std::string, cmCPackComponent>::iterator compIt;
      for (compIt = this->Components.begin(); compIt != this->Components.end();
           ++compIt) {
        // Does the component belong to a group?
        if (compIt->second.Group == nullptr) {
          cmCPackLogger(
            cmCPackLog::LOG_VERBOSE,
            "Component <"
              << compIt->second.Name
              << "> does not belong to any group, package it separately."
              << std::endl);
          retval &= PackageOnePack(initialTopLevel, compIt->first);
        }
      }
    }
    // CPACK_COMPONENTS_IGNORE_GROUPS is set
    // We build 1 package per component
    else {
      std::map<std::string, cmCPackComponent>::iterator compIt;
      for (compIt = this->Components.begin(); compIt != this->Components.end();
           ++compIt) {
        retval &= PackageOnePack(initialTopLevel, compIt->first);
      }
    }
  } else {
    cmCPackLogger(
      cmCPackLog::LOG_ERROR,
      "CPACK_RPM_MAIN_COMPONENT not set but"
        << " it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE"
        << " being set.\n");
    retval = 0;
  }

  if (retval) {
    AddGeneratedPackageNames();
  }

  return retval;
}

int cmCPackRPMGenerator::PackageComponentsAllInOne(
  const std::string& compInstDirName)
{
  int retval = 1;
  /* Reset package file name list it will be populated during the
   * component packaging run*/
  packageFileNames.clear();
  std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));

  if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
    this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON");
  }

  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "Packaging all groups in one package..."
                "(CPACK_COMPONENTS_ALL_[GROUPS_]IN_ONE_PACKAGE is set)"
                  << std::endl);

  // The ALL GROUPS in ONE package case
  std::string localToplevel(initialTopLevel);
  std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
  std::string outputFileName(
    std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
    this->GetOutputExtension());
  // all GROUP in one vs all COMPONENT in one
  localToplevel += "/" + compInstDirName;

  /* replace the TEMP DIRECTORY with the component one */
  this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
  packageFileName += "/" + outputFileName;
  /* replace proposed CPACK_OUTPUT_FILE_NAME */
  this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
  /* replace the TEMPORARY package file name */
  this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
                  packageFileName.c_str());

  if (!compInstDirName.empty()) {
    // Tell CPackRPM.cmake the path where the component is.
    std::string component_path = cmStrCat('/', compInstDirName);
    this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
                    component_path.c_str());
  }

  if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
    AddGeneratedPackageNames();
  } else {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Error while execution CPackRPM.cmake" << std::endl);
    retval = 0;
  }

  return retval;
}

int cmCPackRPMGenerator::PackageFiles()
{
  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);

  /* Are we in the component packaging case */
  if (WantsComponentInstallation()) {
    // CASE 1 : COMPONENT ALL-IN-ONE package
    // If ALL COMPONENTS in ONE package has been requested
    // then the package file is unique and should be open here.
    if (componentPackageMethod == ONE_PACKAGE) {
      return PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
    }
    // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
    // There will be 1 package for each component group
    // however one may require to ignore component group and
    // in this case you'll get 1 package for each component.
    return PackageComponents(componentPackageMethod ==
                             ONE_PACKAGE_PER_COMPONENT);
  }
  // CASE 3 : NON COMPONENT package.
  return PackageComponentsAllInOne("");
}

bool cmCPackRPMGenerator::SupportsComponentInstallation() const
{
  return IsOn("CPACK_RPM_COMPONENT_INSTALL");
}

std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
  const std::string& componentName)
{
  if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
    return componentName;
  }

  if (componentPackageMethod == ONE_PACKAGE) {
    return std::string("ALL_COMPONENTS_IN_ONE");
  }
  // We have to find the name of the COMPONENT GROUP
  // the current COMPONENT belongs to.
  std::string groupVar =
    "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
  if (nullptr != GetOption(groupVar)) {
    return std::string(GetOption(groupVar));
  }
  return componentName;
}
