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

#include <lib/syslog/cpp/macros.h>
#include <stdlib.h>

#include <regex>
#include <sstream>
#include <string_view>
#include <vector>

#include "src/developer/shell/parser/ast.h"
#include "src/developer/shell/parser/parser.h"

namespace shell::console {

Command::Command() = default;

Command::~Command() = default;

namespace {

// Walk a parse tree for errors and collect their messages into the given output stringstream.
void CollectErrors(const parser::ast::Node& node, std::stringstream* out) {
  if (auto err = node.AsError()) {
    if (out->tellp() > 0) {
      (*out) << "\n";
    }

    (*out) << err->message();
  } else {
    for (const auto& child : node.Children()) {
      CollectErrors(*child, out);
    }
  }
}

// Walk a parse tree for errors and collect their messages.
std::string CollectErrors(const parser::ast::Node& node) {
  std::stringstream out;
  CollectErrors(node, &out);
  return out.str();
}

struct IdAndType {
  AstBuilder::NodeId id;
  llcpp::fuchsia::shell::ShellType type;
};

// Visitor for loading a parser AST into a FIDL AST.
class NodeASTVisitor : public parser::ast::NodeVisitor<IdAndType> {
 public:
  explicit NodeASTVisitor(AstBuilder* builder) : builder_(builder) {}

  IdAndType VisitNode(const parser::ast::Node& node) override {
    FX_NOTREACHED() << "Parser produced unknown node type.";
    return {};
  }

  IdAndType VisitProgram(const parser::ast::Program& node) override {
    // TODO: Multiple statements.
    for (const auto& child : node.Children()) {
      if (auto ch = child->AsVariableDecl()) {
        auto ret = VisitVariableDecl(*ch);
        // Return the value of the variable to the command line when done evaluating.
        builder_->AddEmitResult(builder_->AddVariable(ch->identifier()));
        return ret;
      }
    }

    FX_NOTREACHED();
    return {};
  }

  IdAndType VisitVariableDecl(const parser::ast::VariableDecl& node) override {
    IdAndType expression = node.expression()->Visit(this);
    AstBuilder::NodeId id = builder_->AddVariableDeclaration(
        node.identifier(), std::move(expression.type), expression.id, false);

    return {.id = id, .type = llcpp::fuchsia::shell::ShellType()};
  }

  IdAndType VisitInteger(const parser::ast::Integer& node) override {
    AstBuilder::NodeId id = builder_->AddIntegerLiteral(node.value());
    llcpp::fuchsia::shell::BuiltinType builtin_type = llcpp::fuchsia::shell::BuiltinType::INTEGER;
    llcpp::fuchsia::shell::BuiltinType* type_ptr = builder_->ManageCopyOf(&builtin_type);
    llcpp::fuchsia::shell::ShellType type =
        llcpp::fuchsia::shell::ShellType::WithBuiltinType(fidl::unowned_ptr(type_ptr));

    return {.id = id, .type = std::move(type)};
  }

  IdAndType VisitIdentifier(const parser::ast::Identifier& node) override {
    FX_NOTREACHED() << "Variable fetches are unimplemented." << node.identifier();
    return {};
  }

  IdAndType VisitPath(const parser::ast::Path& node) override {
    FX_NOTREACHED() << "Paths are unimplemented.";
    return {};
  }

  IdAndType VisitAddSub(const parser::ast::AddSub& node) override {
    FX_DCHECK(node.type() == parser::ast::AddSub::kAdd) << "Subtraction is unimplemented.";
    AstBuilder::NodeId a_id = node.a()->Visit(this).id;
    IdAndType b_value = node.b()->Visit(this);
    AstBuilder::NodeId b_id = b_value.id;

    AstBuilder::NodeId id = builder_->AddAddition(/*with_exceptions=*/false, a_id, b_id);
    return {.id = id, .type = std::move(b_value.type)};
  }

  IdAndType VisitExpression(const parser::ast::Expression& node) override {
    FX_DCHECK(node.Children().size() > 0);
    return node.Children()[0]->Visit(this);
  }

  IdAndType VisitString(const parser::ast::String& node) override {
    AstBuilder::NodeId id = builder_->AddStringLiteral(node.value());
    llcpp::fuchsia::shell::BuiltinType builtin_type = llcpp::fuchsia::shell::BuiltinType::STRING;
    llcpp::fuchsia::shell::BuiltinType* type_ptr = builder_->ManageCopyOf(&builtin_type);
    llcpp::fuchsia::shell::ShellType type =
        llcpp::fuchsia::shell::ShellType::WithBuiltinType(fidl::unowned_ptr(type_ptr));
    return {.id = id, .type = std::move(type)};
  }

  IdAndType VisitObject(const parser::ast::Object& node) override {
    builder_->OpenObject();

    for (const auto& field : node.fields()) {
      field->Visit(this);
    }

    auto result = builder_->CloseObject();
    AstBuilder::NodeId id = result.value_node;

    llcpp::fuchsia::shell::NodeId shell_id;
    shell_id = result.schema_node;
    llcpp::fuchsia::shell::NodeId* id_ptr = builder_->ManageCopyOf(&shell_id);
    llcpp::fuchsia::shell::ShellType type =
        llcpp::fuchsia::shell::ShellType::WithObjectSchema(fidl::unowned_ptr(id_ptr));

    return {.id = id, .type = std::move(type)};
  }

  IdAndType VisitField(const parser::ast::Field& node) override {
    IdAndType value = node.value()->Visit(this);
    builder_->AddField(node.name(), value.id, std::move(value.type));
    return {};
  }

 private:
  AstBuilder* builder_;
};

}  // namespace

bool Command::Parse(const std::string& line) {
  if (line.empty()) {
    return true;
  }

  auto node = parser::Parse(line);

  FX_DCHECK(node) << "Error handling failed.";

  if (node->HasErrors()) {
    parse_error_ = Err(ErrorType::kBadParse, CollectErrors(*node));
    return false;
  }

  auto program = node->AsProgram();
  FX_DCHECK(program) << "Parse did not yield a program node!";

  // TODO: Change the file ID to something useful.
  AstBuilder builder(1);
  NodeASTVisitor visitor(&builder);
  IdAndType value = program->Visit(&visitor);
  builder.SetRoot(value.id);
  accumulated_nodes_ = std::move(builder);

  return true;
}

}  // namespace shell::console
