// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/utils/io/command.h"

#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sstream>
#include <vector>

namespace tint {
namespace utils {

namespace {

/// File is a simple wrapper around a POSIX file descriptor
class File {
  constexpr static const int kClosed = -1;

 public:
  /// Constructor
  File() : handle_(kClosed) {}

  /// Constructor
  explicit File(int handle) : handle_(handle) {}

  /// Destructor
  ~File() { Close(); }

  /// Move assignment operator
  File& operator=(File&& rhs) {
    Close();
    handle_ = rhs.handle_;
    rhs.handle_ = kClosed;
    return *this;
  }

  /// Closes the file (if it wasn't already closed)
  void Close() {
    if (handle_ != kClosed) {
      close(handle_);
    }
    handle_ = kClosed;
  }

  /// @returns the file handle
  operator int() { return handle_; }

  /// @returns true if the file is not closed
  operator bool() { return handle_ != kClosed; }

 private:
  File(const File&) = delete;
  File& operator=(const File&) = delete;

  int handle_ = kClosed;
};

/// Pipe is a simple wrapper around a POSIX pipe() function
class Pipe {
 public:
  /// Constructs the pipe
  Pipe() {
    int pipes[2] = {};
    if (pipe(pipes) == 0) {
      read = File(pipes[0]);
      write = File(pipes[1]);
    }
  }

  /// Closes both the read and write files (if they're not already closed)
  void Close() {
    read.Close();
    write.Close();
  }

  /// @returns true if the pipe has an open read or write file
  operator bool() { return read || write; }

  /// The reader end of the pipe
  File read;

  /// The writer end of the pipe
  File write;
};

bool ExecutableExists(const std::string& path) {
  struct stat s {};
  if (stat(path.c_str(), &s) != 0) {
    return false;
  }
  return s.st_mode & S_IXUSR;
}

std::string FindExecutable(const std::string& name) {
  if (ExecutableExists(name)) {
    return name;
  }
  if (name.find("/") == std::string::npos) {
    auto* path_env = getenv("PATH");
    if (!path_env) {
      return "";
    }
    std::istringstream path{path_env};
    std::string dir;
    while (getline(path, dir, ':')) {
      auto test = dir + "/" + name;
      if (ExecutableExists(test)) {
        return test;
      }
    }
  }
  return "";
}

}  // namespace

Command::Command(const std::string& path) : path_(path) {}

Command Command::LookPath(const std::string& executable) {
  return Command(FindExecutable(executable));
}

bool Command::Found() const {
  return ExecutableExists(path_);
}

Command::Output Command::Exec(
    std::initializer_list<std::string> arguments) const {
  if (!Found()) {
    Output out;
    out.err = "Executable not found";
    return out;
  }

  // Pipes used for piping std[in,out,err] to / from the target process.
  Pipe stdin_pipe;
  Pipe stdout_pipe;
  Pipe stderr_pipe;

  if (!stdin_pipe || !stdout_pipe || !stderr_pipe) {
    Output output;
    output.err = "Command::Exec(): Failed to create pipes";
    return output;
  }

  // execv() and friends replace the current process image with the target
  // process image. To keep process that called this function going, we need to
  // fork() this process into a child and parent process.
  //
  // The child process is responsible for hooking up the pipes to
  // std[in,out,err]_pipes to STD[IN,OUT,ERR]_FILENO and then calling execv() to
  // run the target command.
  //
  // The parent process is responsible for feeding any input to the stdin_pipe
  // and collectting output from the std[out,err]_pipes.

  int child_id = fork();
  if (child_id < 0) {
    Output output;
    output.err = "Command::Exec(): fork() failed";
    return output;
  }

  if (child_id > 0) {
    // fork() - parent

    // Close the stdout and stderr writer pipes.
    // This is required for getting poll() POLLHUP events.
    stdout_pipe.write.Close();
    stderr_pipe.write.Close();

    // Write the input to the child process
    if (!input_.empty()) {
      ssize_t n = write(stdin_pipe.write, input_.data(), input_.size());
      if (n != static_cast<ssize_t>(input_.size())) {
        Output output;
        output.err = "Command::Exec(): write() for stdin failed";
        return output;
      }
    }
    stdin_pipe.write.Close();

    // Accumulate the stdout and stderr output from the child process
    pollfd poll_fds[2];
    poll_fds[0].fd = stdout_pipe.read;
    poll_fds[0].events = POLLIN;
    poll_fds[1].fd = stderr_pipe.read;
    poll_fds[1].events = POLLIN;

    Output output;
    bool stdout_open = true;
    bool stderr_open = true;
    while (stdout_open || stderr_open) {
      if (poll(poll_fds, 2, -1) < 0) {
        break;
      }
      char buf[256];
      if (poll_fds[0].revents & POLLIN) {
        auto n = read(stdout_pipe.read, buf, sizeof(buf));
        if (n > 0) {
          output.out += std::string(buf, buf + n);
        }
      }
      if (poll_fds[0].revents & POLLHUP) {
        stdout_open = false;
      }
      if (poll_fds[1].revents & POLLIN) {
        auto n = read(stderr_pipe.read, buf, sizeof(buf));
        if (n > 0) {
          output.err += std::string(buf, buf + n);
        }
      }
      if (poll_fds[1].revents & POLLHUP) {
        stderr_open = false;
      }
    }

    // Get the resulting error code
    waitpid(child_id, &output.error_code, 0);

    return output;
  } else {
    // fork() - child

    // Redirect the stdin, stdout, stderr pipes for the execv process
    if ((dup2(stdin_pipe.read, STDIN_FILENO) == -1) ||
        (dup2(stdout_pipe.write, STDOUT_FILENO) == -1) ||
        (dup2(stderr_pipe.write, STDERR_FILENO) == -1)) {
      fprintf(stderr, "Command::Exec(): Failed to redirect pipes");
      exit(errno);
    }

    // Close the pipes, once redirected above, we're now done with them.
    stdin_pipe.Close();
    stdout_pipe.Close();
    stderr_pipe.Close();

    // Run target executable
    std::vector<const char*> args;
    args.emplace_back(path_.c_str());
    for (auto& arg : arguments) {
      args.emplace_back(arg.c_str());
    }
    args.emplace_back(nullptr);
    auto res = execv(path_.c_str(), const_cast<char* const*>(args.data()));
    exit(res);
  }
}

}  // namespace utils
}  // namespace tint
