// 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;
  fuchsia_shell::wire::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 = fuchsia_shell::wire::ShellType()};
  }

  IdAndType VisitInteger(const parser::ast::Integer& node) override {
    AstBuilder::NodeId id = builder_->AddIntegerLiteral(node.value());
    fidl::ObjectView<fuchsia_shell::wire::BuiltinType> builtin_type(
        builder_->allocator(), fuchsia_shell::wire::BuiltinType::kInteger);
    return {.id = id, .type = fuchsia_shell::wire::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 = fuchsia_shell::wire::ShellType::WithBuiltinType(
                builder_->allocator(), fuchsia_shell::wire::BuiltinType::kString)};
  }

  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 = fuchsia_shell::wire::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
