// Copyright 2021 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "common/lsp/lsp-text-buffer.h"

#include <numeric>
#include <string>
#include <vector>

#include "common/strings/utf8.h"

namespace verible {
namespace lsp {
EditTextBuffer::EditTextBuffer(absl::string_view initial_text) {
  ReplaceDocument(initial_text);
}

void EditTextBuffer::ApplyChanges(
    const std::vector<TextDocumentContentChangeEvent> &cc) {
  for (const auto &c : cc) ApplyChange(c);
}

bool EditTextBuffer::ApplyChange(const TextDocumentContentChangeEvent &c) {
  if (!c.has_range) {
    ReplaceDocument(c.text);
    return true;
  }

  if (c.range.end.line >= static_cast<int>(lines_.size())) {
    lines_.emplace_back(new std::string(""));
  }

  if (c.range.start.line == c.range.end.line &&
      c.text.find_first_of('\n') == std::string::npos) {
    return LineEdit(c, lines_[c.range.start.line].get());  // simple case.
  }
  return MultiLineEdit(c);
}

/*static*/ EditTextBuffer::LineVector EditTextBuffer::GenerateLines(
    absl::string_view content) {
  LineVector result;
  for (const absl::string_view s : absl::StrSplit(content, '\n')) {
    result.emplace_back(new std::string(s));
    result.back()->append("\n");
  }

  // Files that do or do not have a newline file-ending: represent correctly.
  if (!content.empty() && content.back() == '\n') {
    result.pop_back();
  } else {
    result.back()->pop_back();
  }

  return result;
}

void EditTextBuffer::ReplaceDocument(absl::string_view content) {
  document_length_ = content.length();
  if (content.empty()) return;
  lines_ = GenerateLines(content);
}

// Return success (might not if input out of range)
bool EditTextBuffer::LineEdit(const TextDocumentContentChangeEvent &c,
                              std::string *str) {
  int end_char = c.range.end.character;

  int str_end = utf8_len(*str);
  if (!str->empty() && str->back() == '\n') --str_end;

  if (c.range.start.character > str_end) return false;
  if (end_char > str_end) end_char = str_end;
  if (end_char < c.range.start.character) return false;

  document_length_ -= str->length();
  const absl::string_view assembly = *str;
  const auto before = utf8_substr(assembly, 0, c.range.start.character);
  const auto after = utf8_substr(assembly, end_char);
  *str = absl::StrCat(before, c.text, after);
  document_length_ += str->length();
  return true;
}

// Returns success (always succeeds);
bool EditTextBuffer::MultiLineEdit(const TextDocumentContentChangeEvent &c) {
  const absl::string_view start_line = *lines_[c.range.start.line];
  const auto before = utf8_substr(start_line, 0, c.range.start.character);

  const absl::string_view end_line = *lines_[c.range.end.line];
  const auto after = utf8_substr(end_line, c.range.end.character);

  // Assemble the full content to replace the range of lines with including
  // the parts that come from the first and last line to be edited.
  const std::string new_content = absl::StrCat(before, c.text, after);

  // Content length update: substract all the bytes that were in the old
  // content and add all in the new content.
  const auto before_begin = lines_.begin() + c.range.start.line;
  const auto before_end = lines_.begin() + c.range.end.line + 1;
  document_length_ -=
      std::accumulate(before_begin, before_end, 0,
                      [](int sum, const LineVector::value_type &line) {
                        return sum + line->length();
                      });
  document_length_ += new_content.length();

  // The new content might include newlines, yielding multiple single lines.
  LineVector regenerated_lines = GenerateLines(new_content);

  // Update the affected lines. Probably not the most optimal but good enough
  lines_.erase(before_begin, before_end);
  lines_.insert(lines_.begin() + c.range.start.line, regenerated_lines.begin(),
                regenerated_lines.end());
  return true;
}

BufferCollection::BufferCollection(JsonRpcDispatcher *dispatcher) {
  // Route notification events from the dispatcher to the buffer collection
  // for them to keep track of what buffers are open and all of their edits
  // they receive.
  dispatcher->AddNotificationHandler(
      "textDocument/didOpen",
      [this](const DidOpenTextDocumentParams &p) { didOpenEvent(p); });
  dispatcher->AddNotificationHandler(
      "textDocument/didClose",
      [this](const DidCloseTextDocumentParams &p) { didCloseEvent(p); });
  dispatcher->AddNotificationHandler(
      "textDocument/didChange",
      [this](const DidChangeTextDocumentParams &p) { didChangeEvent(p); });
}

void BufferCollection::didOpenEvent(const DidOpenTextDocumentParams &o) {
  auto inserted = buffers_.insert({o.textDocument.uri, nullptr});
  if (inserted.second) {
    inserted.first->second.reset(new EditTextBuffer(o.textDocument.text));
    inserted.first->second->set_last_global_version(++global_version_);
    if (change_listener_) {
      change_listener_(o.textDocument.uri, inserted.first->second.get());
    }
  }
}

void BufferCollection::didCloseEvent(const DidCloseTextDocumentParams &o) {
  if (change_listener_) {
    // Let's call the callback first in case our users still have a dangling
    // reference.
    change_listener_(o.textDocument.uri, nullptr);
  }
  buffers_.erase(o.textDocument.uri);
}

void BufferCollection::didChangeEvent(const DidChangeTextDocumentParams &o) {
  auto found = buffers_.find(o.textDocument.uri);
  if (found == buffers_.end()) return;
  EditTextBuffer *const buffer = found->second.get();
  buffer->ApplyChanges(o.contentChanges);
  buffer->set_last_global_version(++global_version_);
  if (change_listener_) change_listener_(o.textDocument.uri, buffer);
}

void EditTextBuffer::RequestContent(const ContentProcessFun &processor) const {
  std::string flat_view;
  flat_view.reserve(document_length_);
  for (const auto &l : lines_) flat_view.append(*l);
  processor(flat_view);
}

void EditTextBuffer::RequestLine(int line,
                                 const ContentProcessFun &processor) const {
  if (line < 0 || line >= static_cast<int>(lines_.size())) {
    processor("");
  } else {
    processor(*lines_[line]);
  }
}
}  // namespace lsp
}  // namespace verible
