/*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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 "process.hpp"

#include <iostream>
#include <sstream>
#include <string.h>

#include <uv.h>

// Create simple console logging functions
#define LOG_MESSAGE(message, is_output)               \
  if (is_output) {                                    \
    std::cerr << "process> " << message << std::endl; \
  }
#define LOG_ERROR(message) LOG_MESSAGE(message, true)

namespace utils {

Process::Result Process::execute(const Args& command) {
  Result result;

  // Create the loop
  uv_loop_t loop;
  uv_loop_init(&loop);
  uv_process_options_t options;
  memset(&options, 0, sizeof(uv_process_options_t));

  // Create the options for reading information from the spawn pipes
  uv_pipe_t standard_output;
  uv_pipe_t standard_error;
  uv_pipe_init(&loop, &standard_output, 0);
  uv_pipe_init(&loop, &standard_error, 0);
  uv_stdio_container_t stdio[3];
  options.stdio_count = 3;
  options.stdio = stdio;
  options.stdio[0].flags = UV_IGNORE;
  options.stdio[1].flags = static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
  options.stdio[1].data.stream = reinterpret_cast<uv_stream_t*>(&standard_output);
  options.stdio[2].flags = static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
  options.stdio[2].data.stream = reinterpret_cast<uv_stream_t*>(&standard_error);

  // Create the options for the process
  std::vector<const char*> args;
  for (Args::const_iterator it = command.begin(), end = command.end(); it != end; ++it) {
    args.push_back(it->c_str());
  }
  args.push_back(NULL);
  options.args = const_cast<char**>(&args[0]);
  options.exit_cb = Process::on_exit;
  options.file = command[0].c_str();

  // Spawn the process
  uv_process_t process;
  process.data = &result;
  int rc = uv_spawn(&loop, &process, &options);
  if (rc == 0) {

    // Configure the storage for the output pipes
    standard_output.data = &result.standard_output;
    standard_error.data = &result.standard_error;

    // Start the output thread loops
    uv_read_start(reinterpret_cast<uv_stream_t*>(&standard_output), Process::on_allocate,
                  Process::on_read);
    uv_read_start(reinterpret_cast<uv_stream_t*>(&standard_error), Process::on_allocate,
                  Process::on_read);

    // Start the process loop
    uv_run(&loop, UV_RUN_DEFAULT);
  } else {
    std::stringstream message;
    message << "Failed to spawn process with error \"" << uv_strerror(rc) << "\"";
    result.standard_error.append(message.str());
  }

  // Close the loop
  rc = uv_loop_close(&loop);
  if (rc != 0) {
    uv_print_all_handles(&loop, stderr);
    if (!result.standard_error.empty()) {
      std::cerr << result.standard_error << std::endl;
    }
    assert(false && "Process loop still has pending handles");
  }

  return result;
}

void Process::on_exit(uv_process_t* process, int64_t exit_status, int term_signal) {
  Result* result = reinterpret_cast<Result*>(process->data);
  result->exit_status = exit_status;
  uv_close(reinterpret_cast<uv_handle_t*>(process), NULL);
}

void Process::on_allocate(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
  buf->base = new char[suggested_size];
  buf->len = suggested_size;
}

void Process::on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
  std::string* message = reinterpret_cast<std::string*>(stream->data);

  if (nread > 0) {
    message->append(buf->base, nread);
  } else if (nread < 0) {
    if (nread != UV_EOF) {
      LOG_ERROR("Failed to read stream with error \"" << uv_strerror(nread) << "\"");
    }
    uv_close(reinterpret_cast<uv_handle_t*>(stream), NULL);
  }

  delete[] buf->base;
}

} // namespace utils
