// 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 {

// TODO: Change the file ID to something useful.
Command::Command() : accumulated_nodes_(1) {}

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());
    fidl::ObjectView<llcpp::fuchsia::shell::BuiltinType> builtin_type(
        builder_->allocator(), llcpp::fuchsia::shell::BuiltinType::INTEGER);
    return {.id = id, .type = llcpp::fuchsia::shell::ShellType::WithBuiltinType(builtin_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());
    return {.id = id,
            .type = llcpp::fuchsia::shell::ShellType::WithBuiltinType(
                builder_->allocator(), llcpp::fuchsia::shell::BuiltinType::STRING)};
  }

  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;
    return {.id = id,
            .type = llcpp::fuchsia::shell::ShellType::WithObjectSchema(builder_->allocator(),
                                                                       result.schema_node)};
  }

  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!";

  NodeASTVisitor visitor(&accumulated_nodes_);
  IdAndType value = program->Visit(&visitor);
  accumulated_nodes_.SetRoot(value.id);

  return true;
}

}  // namespace shell::console
