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

#include <set>
#include <sstream>
#include <utility>

#include <cm/string_view>
#include <cmext/string_view>

#include <sys/types.h>

#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmFSPermissions.h"
#include "cmMakefile.h"
#include "cmNewLineStyle.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

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

  std::string const& inFile = args[0];
  std::string const inputFile = cmSystemTools::CollapseFullPath(
    inFile, status.GetMakefile().GetCurrentSourceDirectory());

  // If the input location is a directory, error out.
  if (cmSystemTools::FileIsDirectory(inputFile)) {
    status.SetError(cmStrCat("input location\n  ", inputFile,
                             "\n"
                             "is a directory but a file was expected."));
    return false;
  }

  std::string const& outFile = args[1];
  std::string outputFile = cmSystemTools::CollapseFullPath(
    outFile, status.GetMakefile().GetCurrentBinaryDirectory());

  // If the output location is already a directory put the file in it.
  if (cmSystemTools::FileIsDirectory(outputFile)) {
    outputFile = cmStrCat(std::move(outputFile), '/',
                          cmSystemTools::GetFilenameName(inFile));
  }

  if (!status.GetMakefile().CanIWriteThisFile(outputFile)) {
    status.SetError(
      cmStrCat("attempted to configure a file: ", std::move(outputFile),
               " into a source directory."));
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }
  std::string errorMessage;
  cmNewLineStyle newLineStyle;
  if (!newLineStyle.ReadFromArguments(args, errorMessage)) {
    status.SetError(errorMessage);
    return false;
  }
  bool copyOnly = false;
  bool escapeQuotes = false;
  bool useSourcePermissions = false;
  bool noSourcePermissions = false;
  bool filePermissions = false;
  std::vector<std::string> filePermissionOptions;

  enum class Doing
  {
    DoingNone,
    DoingFilePermissions,
    DoneFilePermissions
  };

  Doing doing = Doing::DoingNone;

  static std::set<cm::string_view> noopOptions = {
    /* Legacy.  */
    "IMMEDIATE"_s,
    /* Handled by NewLineStyle member.  */
    "NEWLINE_STYLE"_s,
    "LF"_s,
    "UNIX"_s,
    "CRLF"_s,
    "WIN32"_s,
    "DOS"_s,
  };

  std::string unknown_args;
  bool atOnly = false;
  for (unsigned int i = 2; i < args.size(); ++i) {
    if (args[i] == "COPYONLY") {
      if (doing == Doing::DoingFilePermissions) {
        doing = Doing::DoneFilePermissions;
      }
      copyOnly = true;
      if (newLineStyle.IsValid()) {
        status.SetError("COPYONLY could not be used in combination "
                        "with NEWLINE_STYLE");
        return false;
      }
    } else if (args[i] == "ESCAPE_QUOTES") {
      if (doing == Doing::DoingFilePermissions) {
        doing = Doing::DoneFilePermissions;
      }
      escapeQuotes = true;
    } else if (args[i] == "@ONLY") {
      if (doing == Doing::DoingFilePermissions) {
        doing = Doing::DoneFilePermissions;
      }
      atOnly = true;
    } else if (args[i] == "NO_SOURCE_PERMISSIONS") {
      if (doing == Doing::DoingFilePermissions) {
        status.SetError(" given both FILE_PERMISSIONS and "
                        "NO_SOURCE_PERMISSIONS. Only one option allowed.");
        return false;
      }
      noSourcePermissions = true;
    } else if (args[i] == "USE_SOURCE_PERMISSIONS") {
      if (doing == Doing::DoingFilePermissions) {
        status.SetError(" given both FILE_PERMISSIONS and "
                        "USE_SOURCE_PERMISSIONS. Only one option allowed.");
        return false;
      }
      useSourcePermissions = true;
    } else if (args[i] == "FILE_PERMISSIONS") {
      if (useSourcePermissions) {
        status.SetError(" given both FILE_PERMISSIONS and "
                        "USE_SOURCE_PERMISSIONS. Only one option allowed.");
        return false;
      }
      if (noSourcePermissions) {
        status.SetError(" given both FILE_PERMISSIONS and "
                        "NO_SOURCE_PERMISSIONS. Only one option allowed.");
        return false;
      }

      if (doing == Doing::DoingNone) {
        doing = Doing::DoingFilePermissions;
        filePermissions = true;
      }
    } else if (noopOptions.find(args[i]) != noopOptions.end()) {
      /* Ignore no-op options.  */
    } else if (doing == Doing::DoingFilePermissions) {
      filePermissionOptions.push_back(args[i]);
    } else {
      unknown_args = cmStrCat(std::move(unknown_args), ' ', args[i], '\n');
    }
  }
  if (!unknown_args.empty()) {
    status.GetMakefile().IssueDiagnostic(
      cmDiagnostics::CMD_AUTHOR,
      cmStrCat("configure_file called with unknown argument(s):\n",
               unknown_args));
  }

  if (useSourcePermissions && noSourcePermissions) {
    status.SetError(" given both USE_SOURCE_PERMISSIONS and "
                    "NO_SOURCE_PERMISSIONS. Only one option allowed.");
    return false;
  }

  mode_t permissions = 0;

  if (filePermissions) {
    if (filePermissionOptions.empty()) {
      status.SetError(" given FILE_PERMISSIONS without any options.");
      return false;
    }

    std::vector<std::string> invalidOptions;
    for (auto const& e : filePermissionOptions) {
      if (!cmFSPermissions::stringToModeT(e, permissions)) {
        invalidOptions.push_back(e);
      }
    }

    if (!invalidOptions.empty()) {
      std::ostringstream oss;
      oss << " given invalid permission ";
      for (auto i = 0u; i < invalidOptions.size(); i++) {
        if (i == 0u) {
          oss << "\"" << invalidOptions[i] << "\"";
        } else {
          oss << ",\"" << invalidOptions[i] << "\"";
        }
      }
      oss << ".";
      status.SetError(oss.str());
      return false;
    }
  }

  if (noSourcePermissions) {
    permissions |= cmFSPermissions::mode_owner_read;
    permissions |= cmFSPermissions::mode_owner_write;
    permissions |= cmFSPermissions::mode_group_read;
    permissions |= cmFSPermissions::mode_world_read;
  }

  if (!status.GetMakefile().ConfigureFile(inputFile, outputFile, copyOnly,
                                          atOnly, escapeQuotes, permissions,
                                          newLineStyle)) {
    status.SetError("Problem configuring file");
    return false;
  }

  return true;
}
