// 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/app.h"

#include <lib/cmdline/args_parser.h>
#include <unistd.h>
#include <zircon/status.h>

#include <memory>
#include <utility>

namespace shell::console {

const char kHelpIntro[] = R"(cliff [-c <command> ]

  A command line interface for Fuchsia.

Options

)";

const char kHelpHelp[] = R"(  --help
  -h
      Prints all command-line switches.)";

const char kCommandHelp[] = R"(  --command
  -c
      Execute the given command.)";

App::App(fidl::WireSyncClient<fuchsia_shell::Shell>* client, async_dispatcher_t* dispatcher)
    : console_(this, dispatcher, STDIN_FILENO), executor_(client) {}

App::~App() = default;

bool App::Init(int argc, const char** argv, QuitCallback quit_callback) {
  quit_callback_ = std::move(quit_callback);

  cmdline::ArgsParser<Options> parser;
  parser.AddSwitch("command", 'c', kCommandHelp, &Options::command);

  // Special --help switch which doesn't exist in the options structure.
  bool requested_help = false;
  parser.AddGeneralSwitch("help", 'h', kHelpHelp, [&requested_help]() { requested_help = true; });

  std::vector<std::string> params;
  cmdline::Status parser_status = parser.Parse(argc, argv, &options_, &params);
  if (parser_status.has_error()) {
    fprintf(stderr, "error: %s\n", parser_status.error_message().c_str());
    return false;
  }

  // Handle --help switch since we're the one that knows about the switches.
  if (requested_help) {
    printf("%s", (kHelpIntro + parser.GetHelp()).c_str());
    Quit();
    return true;
  }

  console_.Init("% ");

  if (options_.command) {
    auto command = std::make_unique<Command>();
    command->Parse(options_.command.value());
    Err status = OnConsoleCommand(std::move(command));
    if (status.code == ZX_ERR_NEXT) {
      Quit();
    }
    return true;
  } else {
    console_.GetNextCommand();
  }
  return true;
}

Err App::OnConsoleCommand(std::unique_ptr<Command> command) {
  Err status = executor_.Execute(
      std::move(command), [this](const std::string& out) { console_.out() << out << "\n"; },
      [this](const std::string& err) { console_.err() << "Error: " << err << "\n"; },
      [this]() {
        if (options_.command) {
          Quit();
        }
      });
  if (status.code == ZX_ERR_STOP) {
    Quit();
    return status;
  }
  if (status.code > 0 || (status.code != ZX_ERR_NEXT && status.code != ZX_ERR_ASYNC)) {
    console_.err() << "error: Failed to execute command: " << status.code << "(" << status.msg
                   << ")" << std::endl;
    return Err(ZX_ERR_NEXT, zx_status_get_string(ZX_ERR_NEXT));
  }
  return status;
}

void App::OnConsoleInterrupt() {
  executor_.KillForegroundTask();
  console_.GetNextCommand();
}

void App::OnConsoleError(zx_status_t status) {
  fprintf(stderr, "error: Failed to read console: %d (%s)\n", status, zx_status_get_string(status));
  Quit();
}

void App::Quit() {
  auto quit_callback = std::move(quit_callback_);
  quit_callback();
}

}  // namespace shell::console
