// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/shell/console/executor.h"

#include <lib/fdio/spawn.h>
#include <lib/zx/process.h>
#include <zircon/compiler.h>
#include <zircon/status.h>

#include <map>
#include <memory>
#include <vector>

namespace shell::console {

Executor::Executor(llcpp::fuchsia::shell::Shell::SyncClient* client)
    : context_id_(0), client_(client) {}

Executor::~Executor() = default;

Err Executor::Execute(std::unique_ptr<Command> command, fit::closure callback) {
  if (command->nodes().empty()) {
    return Err(ZX_ERR_NEXT, zx_status_get_string(ZX_ERR_NEXT));
  }
  bool done = false;
  context_id_ += 1;
  llcpp::fuchsia::shell::Shell::ResultOf::CreateExecutionContext create_result =
      client_->CreateExecutionContext(context_id_);
  if (!create_result.ok()) {
    return Err(create_result.status(), create_result.error());
  }

  // TODO: Make sure that add_result is small enough to fit in a single FIDL message.  Otherwise,
  // split it.
  llcpp::fuchsia::shell::Shell::ResultOf::AddNodes add_result =
      client_->AddNodes(context_id_, command->nodes().AsVectorView());
  if (!add_result.ok()) {
    return Err(add_result.status(), add_result.error());
  }

  llcpp::fuchsia::shell::Shell::ResultOf::ExecuteExecutionContext execute_result =
      client_->ExecuteExecutionContext(context_id_);
  if (!execute_result.ok()) {
    return Err(execute_result.status(), execute_result.error());
  }

  while (!done) {
    llcpp::fuchsia::shell::Shell::EventHandlers handlers;
    handlers.on_text_result = [](uint64_t context_id, ::fidl::StringView result,
                                 bool partial_result) {
      fprintf(stderr, "Text result: %s\n", result.data());
      return ZX_OK;
    };
    handlers.on_execution_done = [&done](uint64_t context_id,
                                         ::llcpp::fuchsia::shell::ExecuteResult result) {
      done = true;
      return ZX_OK;
    };
    handlers.on_error = [](uint64_t context_id,
                           ::fidl::VectorView<::llcpp::fuchsia::shell::Location> locations,
                           ::fidl::StringView error_message) {
      fprintf(stderr, "Error: %s\n", error_message.data());
      return ZX_OK;
    };
    zx_status_t result = client_->HandleEvents(std::move(handlers));
    if (result != ZX_OK) {
      return Err(result, zx_status_get_string(result));
    }
  }

  return Err(ZX_ERR_NEXT, zx_status_get_string(ZX_ERR_NEXT));
}

void Executor::KillForegroundTask() {
  // TODO(fidl-tools-team): What happens when we hit ^C?
}

}  // namespace shell::console
