// 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 <iomanip>
#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(std::string_view line, const parser::ast::Node& node, std::stringstream* out) {
  if (auto err = node.AsError()) {
    size_t err_end = err->start() + err->Size();
    size_t line_start_offset = 0;
    size_t line_start = 1;

    for (size_t i = 0; i < err->start(); i++) {
      if (line[i] == '\n') {
        line_start_offset = i + 1;
        line_start++;
      }
    }

    size_t line_end = line_start;

    for (size_t i = line_start_offset; i < err_end; i++) {
      if (line[i] == '\n') {
        line_end++;
      }
    }

    size_t line_pad = std::to_string(line_end).size();
    size_t line_number = line_start;
    size_t start = line_start_offset;

    do {
      auto prev_width = out->width(line_pad);
      (*out) << line_number;
      out->width(prev_width);
      (*out) << ": ";
      size_t end = line.find('\n', start);

      if (end == std::string::npos) {
        end = line.size();
      }

      (*out) << line.substr(start, end - start) << "\n" << std::string(line_pad + 2, ' ');

      for (size_t i = start; i <= end; i++) {
        if (i == err->start()) {
          (*out) << "^";

          if (i != err_end) {
            continue;
          }
        }

        if (i < err->start()) {
          (*out) << " ";
        } else if (i == err_end) {
          (*out) << " " << err->message();
          break;
        } else {
          (*out) << "~";
        }
      }

      (*out) << "\n\n";
      start = end + 1;
      line_number += 1;
    } while (start <= err_end);
  } else {
    for (const auto& child : node.Children()) {
      CollectErrors(line, *child, out);
    }
  }
}

// Walk a parse tree for errors and collect their messages.
std::string CollectErrors(std::string_view line, const parser::ast::Node& node) {
  std::stringstream out;
  CollectErrors(line, 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_ = CollectErrors(line, *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
