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

#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"

class cmExecutionStatus;

static void FinalAction(cmMakefile& makefile, std::string const& dest,
                        std::vector<std::string> const& args);
static std::string FindInstallSource(cmMakefile& makefile, const char* name);

// cmExecutableCommand
bool cmInstallProgramsCommand::InitialPass(
  std::vector<std::string> const& args, cmExecutionStatus&)
{
  if (args.size() < 2) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // Enable the install target.
  this->Makefile->GetGlobalGenerator()->EnableInstallTarget();

  this->Makefile->GetGlobalGenerator()->AddInstallComponent(
    this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));

  std::string const& dest = args[0];
  std::vector<std::string> const finalArgs(args.begin() + 1, args.end());
  this->Makefile->AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
    FinalAction(makefile, dest, finalArgs);
  });
  return true;
}

static void FinalAction(cmMakefile& makefile, std::string const& dest,
                        std::vector<std::string> const& args)
{
  bool files_mode = false;
  if (!args.empty() && args[0] == "FILES") {
    files_mode = true;
  }

  std::vector<std::string> files;

  // two different options
  if (args.size() > 1 || files_mode) {
    // for each argument, get the programs
    std::vector<std::string>::const_iterator s = args.begin();
    if (files_mode) {
      // Skip the FILES argument in files mode.
      ++s;
    }
    for (; s != args.end(); ++s) {
      // add to the result
      files.push_back(FindInstallSource(makefile, s->c_str()));
    }
  } else // reg exp list
  {
    std::vector<std::string> programs;
    cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), args[0],
                        programs);

    std::vector<std::string>::iterator s = programs.begin();
    // for each argument, get the programs
    for (; s != programs.end(); ++s) {
      files.push_back(FindInstallSource(makefile, s->c_str()));
    }
  }

  // Construct the destination.  This command always installs under
  // the prefix.  We skip the leading slash given by the user.
  std::string destination = dest.substr(1);
  cmSystemTools::ConvertToUnixSlashes(destination);
  if (destination.empty()) {
    destination = ".";
  }

  // Use a file install generator.
  const char* no_permissions = "";
  const char* no_rename = "";
  bool no_exclude_from_all = false;
  std::string no_component =
    makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
  std::vector<std::string> no_configurations;
  cmInstallGenerator::MessageLevel message =
    cmInstallGenerator::SelectMessageLevel(&makefile);
  makefile.AddInstallGenerator(new cmInstallFilesGenerator(
    files, destination.c_str(), true, no_permissions, no_configurations,
    no_component.c_str(), message, no_exclude_from_all, no_rename));
}

/**
 * Find a file in the build or source tree for installation given a
 * relative path from the CMakeLists.txt file.  This will favor files
 * present in the build tree.  If a full path is given, it is just
 * returned.
 */
static std::string FindInstallSource(cmMakefile& makefile, const char* name)
{
  if (cmSystemTools::FileIsFullPath(name) ||
      cmGeneratorExpression::Find(name) == 0) {
    // This is a full path.
    return name;
  }

  // This is a relative path.
  std::string tb = makefile.GetCurrentBinaryDirectory();
  tb += "/";
  tb += name;
  std::string ts = makefile.GetCurrentSourceDirectory();
  ts += "/";
  ts += name;

  if (cmSystemTools::FileExists(tb)) {
    // The file exists in the binary tree.  Use it.
    return tb;
  }
  if (cmSystemTools::FileExists(ts)) {
    // The file exists in the source tree.  Use it.
    return ts;
  }
  // The file doesn't exist.  Assume it will be present in the
  // binary tree when the install occurs.
  return tb;
}
