// Copyright 2019 the V8 project 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 <algorithm>
#include "src/torque/ls/message-handler.h"

#include "src/torque/ls/globals.h"
#include "src/torque/ls/json-parser.h"
#include "src/torque/ls/message-pipe.h"
#include "src/torque/ls/message.h"
#include "src/torque/server-data.h"
#include "src/torque/source-positions.h"
#include "src/torque/torque-compiler.h"

namespace v8 {
namespace internal {
namespace torque {

DEFINE_CONTEXTUAL_VARIABLE(Logger)
DEFINE_CONTEXTUAL_VARIABLE(TorqueFileList)
DEFINE_CONTEXTUAL_VARIABLE(DiagnosticsFiles)

namespace ls {

static const char kContentLength[] = "Content-Length: ";
static const size_t kContentLengthSize = sizeof(kContentLength) - 1;

#ifdef V8_OS_WIN
// On Windows, in text mode, \n is translated to \r\n.
constexpr const char* kProtocolLineEnding = "\n\n";
#else
constexpr const char* kProtocolLineEnding = "\r\n\r\n";
#endif

JsonValue ReadMessage() {
  std::string line;
  std::getline(std::cin, line);

  if (line.rfind(kContentLength) != 0) {
    // Invalid message, we just crash.
    Logger::Log("[fatal] Did not find Content-Length ...\n");
    v8::base::OS::Abort();
  }

  const int content_length = std::atoi(line.substr(kContentLengthSize).c_str());
  std::getline(std::cin, line);
  std::string content(content_length, ' ');
  std::cin.read(&content[0], content_length);

  Logger::Log("[incoming] ", content, "\n\n");

  return ParseJson(content).value;
}

void WriteMessage(JsonValue message) {
  std::string content = SerializeToString(message);

  Logger::Log("[outgoing] ", content, "\n\n");

  std::cout << kContentLength << content.size() << kProtocolLineEnding;
  std::cout << content << std::flush;
}

namespace {

void ResetCompilationErrorDiagnostics(MessageWriter writer) {
  for (const SourceId& source : DiagnosticsFiles::Get()) {
    PublishDiagnosticsNotification notification;
    notification.set_method("textDocument/publishDiagnostics");

    std::string error_file = SourceFileMap::AbsolutePath(source);
    notification.params().set_uri(error_file);
    // Trigger empty array creation.
    USE(notification.params().diagnostics_size());

    writer(std::move(notification.GetJsonValue()));
  }
  DiagnosticsFiles::Get() = {};
}

// Each notification must contain all diagnostics for a specific file,
// because sending multiple notifications per file resets previously sent
// diagnostics. Thus, two steps are needed:
//   1) collect all notifications in this class.
//   2) send one notification per entry (per file).
class DiagnosticCollector {
 public:
  void AddTorqueMessage(const TorqueMessage& message) {
    if (!ShouldAddMessageOfKind(message.kind)) return;

    SourceId id =
        message.position ? message.position->source : SourceId::Invalid();
    auto& notification = GetOrCreateNotificationForSource(id);

    Diagnostic diagnostic = notification.params().add_diagnostics();
    diagnostic.set_severity(ServerityFor(message.kind));
    diagnostic.set_message(message.message);
    diagnostic.set_source("Torque Compiler");

    if (message.position) {
      PopulateRangeFromSourcePosition(diagnostic.range(), *message.position);
    }
  }

  std::map<SourceId, PublishDiagnosticsNotification>& notifications() {
    return notifications_;
  }

 private:
  PublishDiagnosticsNotification& GetOrCreateNotificationForSource(
      SourceId id) {
    auto iter = notifications_.find(id);
    if (iter != notifications_.end()) return iter->second;

    PublishDiagnosticsNotification& notification = notifications_[id];
    notification.set_method("textDocument/publishDiagnostics");

    std::string file =
        id.IsValid() ? SourceFileMap::AbsolutePath(id) : "<unknown>";
    notification.params().set_uri(file);
    return notification;
  }

  bool ShouldAddMessageOfKind(TorqueMessage::Kind kind) {
    // An error can easily cause a lot of false positive lint messages, due to
    // unused variables, macros, etc. Thus we suppress subsequent lint messages
    // when there are errors.
    switch (kind) {
      case TorqueMessage::Kind::kError:
        suppress_lint_messages_ = true;
        return true;
      case TorqueMessage::Kind::kLint:
        if (suppress_lint_messages_) return false;
        return true;
    }
  }

  void PopulateRangeFromSourcePosition(Range range,
                                       const SourcePosition& position) {
    range.start().set_line(position.start.line);
    range.start().set_character(position.start.column);
    range.end().set_line(position.end.line);
    range.end().set_character(position.end.column);
  }

  Diagnostic::DiagnosticSeverity ServerityFor(TorqueMessage::Kind kind) {
    switch (kind) {
      case TorqueMessage::Kind::kError:
        return Diagnostic::kError;
      case TorqueMessage::Kind::kLint:
        return Diagnostic::kWarning;
    }
  }

  std::map<SourceId, PublishDiagnosticsNotification> notifications_;
  bool suppress_lint_messages_ = false;
};

void SendCompilationDiagnostics(const TorqueCompilerResult& result,
                                MessageWriter writer) {
  DiagnosticCollector collector;

  // TODO(szuend): Split up messages by SourceId and sort them by line number.
  for (const TorqueMessage& message : result.messages) {
    collector.AddTorqueMessage(message);
  }

  for (auto& pair : collector.notifications()) {
    PublishDiagnosticsNotification& notification = pair.second;
    writer(std::move(notification.GetJsonValue()));

    // Record all source files for which notifications are sent, so they
    // can be reset before the next compiler run.
    const SourceId& source = pair.first;
    if (source.IsValid()) DiagnosticsFiles::Get().push_back(source);
  }
}

}  // namespace

void CompilationFinished(TorqueCompilerResult result, MessageWriter writer) {
  LanguageServerData::Get() = std::move(result.language_server_data);
  SourceFileMap::Get() = *result.source_file_map;

  SendCompilationDiagnostics(result, writer);
}

namespace {

void RecompileTorque(MessageWriter writer) {
  Logger::Log("[info] Start compilation run ...\n");

  TorqueCompilerOptions options;
  options.output_directory = "";
  options.collect_language_server_data = true;
  options.force_assert_statements = true;

  TorqueCompilerResult result = CompileTorque(TorqueFileList::Get(), options);

  Logger::Log("[info] Finished compilation run ...\n");

  CompilationFinished(std::move(result), writer);
}

void RecompileTorqueWithDiagnostics(MessageWriter writer) {
  ResetCompilationErrorDiagnostics(writer);
  RecompileTorque(writer);
}

void HandleInitializeRequest(InitializeRequest request, MessageWriter writer) {
  InitializeResponse response;
  response.set_id(request.id());
  response.result().capabilities().textDocumentSync();
  response.result().capabilities().set_definitionProvider(true);
  response.result().capabilities().set_documentSymbolProvider(true);

  // TODO(szuend): Register for document synchronisation here,
  //               so we work with the content that the client
  //               provides, not directly read from files.
  // TODO(szuend): Check that the client actually supports dynamic
  //               "workspace/didChangeWatchedFiles" capability.
  // TODO(szuend): Check if client supports "LocationLink". This will
  //               influence the result of "goto definition".
  writer(std::move(response.GetJsonValue()));
}

void HandleInitializedNotification(MessageWriter writer) {
  RegistrationRequest request;
  // TODO(szuend): The language server needs a "global" request id counter.
  request.set_id(2000);
  request.set_method("client/registerCapability");

  Registration reg = request.params().add_registrations();
  auto options =
      reg.registerOptions<DidChangeWatchedFilesRegistrationOptions>();
  FileSystemWatcher watcher = options.add_watchers();
  watcher.set_globPattern("**/*.tq");
  watcher.set_kind(FileSystemWatcher::WatchKind::kAll);

  reg.set_id("did-change-id");
  reg.set_method("workspace/didChangeWatchedFiles");

  writer(std::move(request.GetJsonValue()));
}

void HandleTorqueFileListNotification(TorqueFileListNotification notification,
                                      MessageWriter writer) {
  CHECK_EQ(notification.params().object()["files"].tag, JsonValue::ARRAY);

  std::vector<std::string>& files = TorqueFileList::Get();
  Logger::Log("[info] Initial file list:\n");
  for (const auto& file_json :
       notification.params().object()["files"].ToArray()) {
    CHECK(file_json.IsString());

    // We only consider file URIs (there shouldn't be anything else).
    // Internally we store the URI instead of the path, eliminating the need
    // to encode it again.
    files.push_back(file_json.ToString());
    Logger::Log("    ", file_json.ToString(), "\n");
  }
  RecompileTorqueWithDiagnostics(writer);
}

void HandleGotoDefinitionRequest(GotoDefinitionRequest request,
                                 MessageWriter writer) {
  GotoDefinitionResponse response;
  response.set_id(request.id());

  SourceId id =
      SourceFileMap::GetSourceId(request.params().textDocument().uri());

  // Unknown source files cause an empty response which corresponds with
  // the definition not beeing found.
  if (!id.IsValid()) {
    response.SetNull("result");
    writer(std::move(response.GetJsonValue()));
    return;
  }

  LineAndColumn pos{request.params().position().line(),
                    request.params().position().character()};

  if (auto maybe_definition = LanguageServerData::FindDefinition(id, pos)) {
    SourcePosition definition = *maybe_definition;
    response.result().SetTo(definition);
  } else {
    response.SetNull("result");
  }

  writer(std::move(response.GetJsonValue()));
}

void HandleChangeWatchedFilesNotification(
    DidChangeWatchedFilesNotification notification, MessageWriter writer) {
  // TODO(szuend): Implement updates to the TorqueFile list when create/delete
  //               notifications are received. Currently we simply re-compile.
  RecompileTorqueWithDiagnostics(writer);
}

void HandleDocumentSymbolRequest(DocumentSymbolRequest request,
                                 MessageWriter writer) {
  DocumentSymbolResponse response;
  response.set_id(request.id());

  SourceId id =
      SourceFileMap::GetSourceId(request.params().textDocument().uri());

  for (const auto& symbol : LanguageServerData::SymbolsForSourceId(id)) {
    DCHECK(symbol->IsUserDefined());
    if (symbol->IsMacro()) {
      Macro* macro = Macro::cast(symbol);
      SymbolInformation symbol = response.add_result();
      symbol.set_name(macro->ReadableName());
      symbol.set_kind(SymbolKind::kFunction);
      symbol.location().SetTo(macro->Position());
    } else if (symbol->IsBuiltin()) {
      Builtin* builtin = Builtin::cast(symbol);
      SymbolInformation symbol = response.add_result();
      symbol.set_name(builtin->ReadableName());
      symbol.set_kind(SymbolKind::kFunction);
      symbol.location().SetTo(builtin->Position());
    } else if (symbol->IsGenericCallable()) {
      GenericCallable* generic = GenericCallable::cast(symbol);
      SymbolInformation symbol = response.add_result();
      symbol.set_name(generic->name());
      symbol.set_kind(SymbolKind::kFunction);
      symbol.location().SetTo(generic->Position());
    } else if (symbol->IsTypeAlias()) {
      const Type* type = TypeAlias::cast(symbol)->type();
      SymbolKind kind =
          type->IsClassType() ? SymbolKind::kClass : SymbolKind::kStruct;

      SymbolInformation sym = response.add_result();
      sym.set_name(type->ToString());
      sym.set_kind(kind);
      sym.location().SetTo(symbol->Position());
    }
  }

  // Trigger empty array creation in case no symbols were found.
  USE(response.result_size());

  writer(std::move(response.GetJsonValue()));
}

}  // namespace

void HandleMessage(JsonValue raw_message, MessageWriter writer) {
  Request<bool> request(std::move(raw_message));

  // We ignore responses for now. They are matched to requests
  // by id and don't have a method set.
  // TODO(szuend): Implement proper response handling for requests
  //               that originate from the server.
  if (!request.has_method()) {
    Logger::Log("[info] Unhandled response with id ", request.id(), "\n\n");
    return;
  }

  const std::string method = request.method();
  if (method == "initialize") {
    HandleInitializeRequest(
        InitializeRequest(std::move(request.GetJsonValue())), writer);
  } else if (method == "initialized") {
    HandleInitializedNotification(writer);
  } else if (method == "torque/fileList") {
    HandleTorqueFileListNotification(
        TorqueFileListNotification(std::move(request.GetJsonValue())), writer);
  } else if (method == "textDocument/definition") {
    HandleGotoDefinitionRequest(
        GotoDefinitionRequest(std::move(request.GetJsonValue())), writer);
  } else if (method == "workspace/didChangeWatchedFiles") {
    HandleChangeWatchedFilesNotification(
        DidChangeWatchedFilesNotification(std::move(request.GetJsonValue())),
        writer);
  } else if (method == "textDocument/documentSymbol") {
    HandleDocumentSymbolRequest(
        DocumentSymbolRequest(std::move(request.GetJsonValue())), writer);
  } else {
    Logger::Log("[error] Message of type ", method, " is not handled!\n\n");
  }
}

}  // namespace ls
}  // namespace torque
}  // namespace internal
}  // namespace v8
