/* 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 <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 += "/";
    outputFile += cmSystemTools::GetFilenameName(inFile);
  }

  if (!status.GetMakefile().CanIWriteThisFile(outputFile)) {
    std::string e = "attempted to configure a file: " + outputFile +
      " into a source directory.";
    status.SetError(e);
    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 += " ";
      unknown_args += args[i];
      unknown_args += "\n";
    }
  }
  if (!unknown_args.empty()) {
    std::string msg = cmStrCat(
      "configure_file called with unknown argument(s):\n", unknown_args);
    status.GetMakefile().IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, msg);
  }

  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;
}
