// 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/tint/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::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 tint::utils
