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

#include "cmsys/Process.h"
#include <ctype.h> /* isspace */
#include <sstream>
#include <stdio.h>

#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
#include "cmSystemTools.h"

class cmExecutionStatus;

static bool cmExecuteProcessCommandIsWhitespace(char c)
{
  return (isspace(static_cast<int>(c)) || c == '\n' || c == '\r');
}

void cmExecuteProcessCommandFixText(std::vector<char>& output,
                                    bool strip_trailing_whitespace);
void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
                                   int length);

// cmExecuteProcessCommand
bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
                                          cmExecutionStatus&)
{
  if (args.empty()) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }
  std::vector<std::vector<const char*>> cmds;
  std::string arguments;
  bool doing_command = false;
  size_t command_index = 0;
  bool output_quiet = false;
  bool error_quiet = false;
  bool output_strip_trailing_whitespace = false;
  bool error_strip_trailing_whitespace = false;
  std::string timeout_string;
  std::string input_file;
  std::string output_file;
  std::string error_file;
  std::string output_variable;
  std::string error_variable;
  std::string result_variable;
  std::string results_variable;
  std::string working_directory;
  cmProcessOutput::Encoding encoding = cmProcessOutput::None;
  for (size_t i = 0; i < args.size(); ++i) {
    if (args[i] == "COMMAND") {
      doing_command = true;
      command_index = cmds.size();
      cmds.emplace_back();
    } else if (args[i] == "OUTPUT_VARIABLE") {
      doing_command = false;
      if (++i < args.size()) {
        output_variable = args[i];
      } else {
        this->SetError(" called with no value for OUTPUT_VARIABLE.");
        return false;
      }
    } else if (args[i] == "ERROR_VARIABLE") {
      doing_command = false;
      if (++i < args.size()) {
        error_variable = args[i];
      } else {
        this->SetError(" called with no value for ERROR_VARIABLE.");
        return false;
      }
    } else if (args[i] == "RESULT_VARIABLE") {
      doing_command = false;
      if (++i < args.size()) {
        result_variable = args[i];
      } else {
        this->SetError(" called with no value for RESULT_VARIABLE.");
        return false;
      }
    } else if (args[i] == "RESULTS_VARIABLE") {
      doing_command = false;
      if (++i < args.size()) {
        results_variable = args[i];
      } else {
        this->SetError(" called with no value for RESULTS_VARIABLE.");
        return false;
      }
    } else if (args[i] == "WORKING_DIRECTORY") {
      doing_command = false;
      if (++i < args.size()) {
        working_directory = args[i];
      } else {
        this->SetError(" called with no value for WORKING_DIRECTORY.");
        return false;
      }
    } else if (args[i] == "INPUT_FILE") {
      doing_command = false;
      if (++i < args.size()) {
        input_file = args[i];
      } else {
        this->SetError(" called with no value for INPUT_FILE.");
        return false;
      }
    } else if (args[i] == "OUTPUT_FILE") {
      doing_command = false;
      if (++i < args.size()) {
        output_file = args[i];
      } else {
        this->SetError(" called with no value for OUTPUT_FILE.");
        return false;
      }
    } else if (args[i] == "ERROR_FILE") {
      doing_command = false;
      if (++i < args.size()) {
        error_file = args[i];
      } else {
        this->SetError(" called with no value for ERROR_FILE.");
        return false;
      }
    } else if (args[i] == "TIMEOUT") {
      doing_command = false;
      if (++i < args.size()) {
        timeout_string = args[i];
      } else {
        this->SetError(" called with no value for TIMEOUT.");
        return false;
      }
    } else if (args[i] == "OUTPUT_QUIET") {
      doing_command = false;
      output_quiet = true;
    } else if (args[i] == "ERROR_QUIET") {
      doing_command = false;
      error_quiet = true;
    } else if (args[i] == "OUTPUT_STRIP_TRAILING_WHITESPACE") {
      doing_command = false;
      output_strip_trailing_whitespace = true;
    } else if (args[i] == "ERROR_STRIP_TRAILING_WHITESPACE") {
      doing_command = false;
      error_strip_trailing_whitespace = true;
    } else if (args[i] == "ENCODING") {
      doing_command = false;
      if (++i < args.size()) {
        encoding = cmProcessOutput::FindEncoding(args[i]);
      } else {
        this->SetError(" called with no value for ENCODING.");
        return false;
      }
    } else if (doing_command) {
      cmds[command_index].push_back(args[i].c_str());
    } else {
      std::ostringstream e;
      e << " given unknown argument \"" << args[i] << "\".";
      this->SetError(e.str());
      return false;
    }
  }

  if (!this->Makefile->CanIWriteThisFile(output_file)) {
    std::string e = "attempted to output into a file: " + output_file +
      " into a source directory.";
    this->SetError(e);
    cmSystemTools::SetFatalErrorOccured();
    return false;
  }

  // Check for commands given.
  if (cmds.empty()) {
    this->SetError(" called with no COMMAND argument.");
    return false;
  }
  for (auto& cmd : cmds) {
    if (cmd.empty()) {
      this->SetError(" given COMMAND argument with no value.");
      return false;
    }
    // Add the null terminating pointer to the command argument list.
    cmd.push_back(nullptr);
  }

  // Parse the timeout string.
  double timeout = -1;
  if (!timeout_string.empty()) {
    if (sscanf(timeout_string.c_str(), "%lg", &timeout) != 1) {
      this->SetError(" called with TIMEOUT value that could not be parsed.");
      return false;
    }
  }

  // Create a process instance.
  cmsysProcess* cp = cmsysProcess_New();

  // Set the command sequence.
  for (auto const& cmd : cmds) {
    cmsysProcess_AddCommand(cp, &*cmd.begin());
  }

  // Set the process working directory.
  if (!working_directory.empty()) {
    cmsysProcess_SetWorkingDirectory(cp, working_directory.c_str());
  }

  // Always hide the process window.
  cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);

  // Check the output variables.
  bool merge_output = false;
  if (!input_file.empty()) {
    cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str());
  }
  if (!output_file.empty()) {
    cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDOUT,
                             output_file.c_str());
  }
  if (!error_file.empty()) {
    if (error_file == output_file) {
      merge_output = true;
    } else {
      cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
                               error_file.c_str());
    }
  }
  if (!output_variable.empty() && output_variable == error_variable) {
    merge_output = true;
  }
  if (merge_output) {
    cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
  }

  // Set the timeout if any.
  if (timeout >= 0) {
    cmsysProcess_SetTimeout(cp, timeout);
  }

  // Start the process.
  cmsysProcess_Execute(cp);

  // Read the process output.
  std::vector<char> tempOutput;
  std::vector<char> tempError;
  int length;
  char* data;
  int p;
  cmProcessOutput processOutput(encoding);
  std::string strdata;
  while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
    // Put the output in the right place.
    if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) {
      if (output_variable.empty()) {
        processOutput.DecodeText(data, length, strdata, 1);
        cmSystemTools::Stdout(strdata);
      } else {
        cmExecuteProcessCommandAppend(tempOutput, data, length);
      }
    } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) {
      if (error_variable.empty()) {
        processOutput.DecodeText(data, length, strdata, 2);
        cmSystemTools::Stderr(strdata);
      } else {
        cmExecuteProcessCommandAppend(tempError, data, length);
      }
    }
  }
  if (!output_quiet && output_variable.empty()) {
    processOutput.DecodeText(std::string(), strdata, 1);
    if (!strdata.empty()) {
      cmSystemTools::Stdout(strdata);
    }
  }
  if (!error_quiet && error_variable.empty()) {
    processOutput.DecodeText(std::string(), strdata, 2);
    if (!strdata.empty()) {
      cmSystemTools::Stderr(strdata);
    }
  }

  // All output has been read.  Wait for the process to exit.
  cmsysProcess_WaitForExit(cp, nullptr);
  processOutput.DecodeText(tempOutput, tempOutput);
  processOutput.DecodeText(tempError, tempError);

  // Fix the text in the output strings.
  cmExecuteProcessCommandFixText(tempOutput, output_strip_trailing_whitespace);
  cmExecuteProcessCommandFixText(tempError, error_strip_trailing_whitespace);

  // Store the output obtained.
  if (!output_variable.empty() && !tempOutput.empty()) {
    this->Makefile->AddDefinition(output_variable, &*tempOutput.begin());
  }
  if (!merge_output && !error_variable.empty() && !tempError.empty()) {
    this->Makefile->AddDefinition(error_variable, &*tempError.begin());
  }

  // Store the result of running the process.
  if (!result_variable.empty()) {
    switch (cmsysProcess_GetState(cp)) {
      case cmsysProcess_State_Exited: {
        int v = cmsysProcess_GetExitValue(cp);
        char buf[16];
        sprintf(buf, "%d", v);
        this->Makefile->AddDefinition(result_variable, buf);
      } break;
      case cmsysProcess_State_Exception:
        this->Makefile->AddDefinition(result_variable,
                                      cmsysProcess_GetExceptionString(cp));
        break;
      case cmsysProcess_State_Error:
        this->Makefile->AddDefinition(result_variable,
                                      cmsysProcess_GetErrorString(cp));
        break;
      case cmsysProcess_State_Expired:
        this->Makefile->AddDefinition(result_variable,
                                      "Process terminated due to timeout");
        break;
    }
  }
  // Store the result of running the processes.
  if (!results_variable.empty()) {
    switch (cmsysProcess_GetState(cp)) {
      case cmsysProcess_State_Exited: {
        std::vector<std::string> res;
        for (size_t i = 0; i < cmds.size(); ++i) {
          switch (cmsysProcess_GetStateByIndex(cp, static_cast<int>(i))) {
            case kwsysProcess_StateByIndex_Exited: {
              int exitCode =
                cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i));
              char buf[16];
              sprintf(buf, "%d", exitCode);
              res.emplace_back(buf);
            } break;
            case kwsysProcess_StateByIndex_Exception:
              res.emplace_back(cmsysProcess_GetExceptionStringByIndex(
                cp, static_cast<int>(i)));
              break;
            case kwsysProcess_StateByIndex_Error:
            default:
              res.emplace_back("Error getting the child return code");
              break;
          }
        }
        this->Makefile->AddDefinition(results_variable,
                                      cmJoin(res, ";").c_str());
      } break;
      case cmsysProcess_State_Exception:
        this->Makefile->AddDefinition(results_variable,
                                      cmsysProcess_GetExceptionString(cp));
        break;
      case cmsysProcess_State_Error:
        this->Makefile->AddDefinition(results_variable,
                                      cmsysProcess_GetErrorString(cp));
        break;
      case cmsysProcess_State_Expired:
        this->Makefile->AddDefinition(results_variable,
                                      "Process terminated due to timeout");
        break;
    }
  }

  // Delete the process instance.
  cmsysProcess_Delete(cp);

  return true;
}

void cmExecuteProcessCommandFixText(std::vector<char>& output,
                                    bool strip_trailing_whitespace)
{
  // Remove \0 characters and the \r part of \r\n pairs.
  unsigned int in_index = 0;
  unsigned int out_index = 0;
  while (in_index < output.size()) {
    char c = output[in_index++];
    if ((c != '\r' ||
         !(in_index < output.size() && output[in_index] == '\n')) &&
        c != '\0') {
      output[out_index++] = c;
    }
  }

  // Remove trailing whitespace if requested.
  if (strip_trailing_whitespace) {
    while (out_index > 0 &&
           cmExecuteProcessCommandIsWhitespace(output[out_index - 1])) {
      --out_index;
    }
  }

  // Shrink the vector to the size needed.
  output.resize(out_index);

  // Put a terminator on the text string.
  output.push_back('\0');
}

void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
                                   int length)
{
#if defined(__APPLE__)
  // HACK on Apple to work around bug with inserting at the
  // end of an empty vector.  This resulted in random failures
  // that were hard to reproduce.
  if (output.empty() && length > 0) {
    output.push_back(data[0]);
    ++data;
    --length;
  }
#endif
  output.insert(output.end(), data, data + length);
}
