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

#ifndef VERIBLE_COMMON_LSP_LSP_TEXT_BUFFER_H
#define VERIBLE_COMMON_LSP_LSP_TEXT_BUFFER_H

#include <functional>
#include <memory>
#include <vector>

//
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "common/lsp/json-rpc-dispatcher.h"
#include "common/lsp/lsp-protocol.h"

namespace verible {
namespace lsp {
// The EditTextBuffer keeps track of the content of buffers on the client.
// It is fed initially with the full content, and from then on receives
// change events to keep in sync.
// It provides ways to pass the current content to a requestor that needs to
// process it.
class EditTextBuffer {
 public:
  using ContentProcessFun = std::function<void(absl::string_view)>;

  explicit EditTextBuffer(absl::string_view initial_text);
  EditTextBuffer(const EditTextBuffer &) = delete;
  EditTextBuffer(EditTextBuffer &&) = delete;

  // Requst to flatten the content call and call function "processor" that
  // gets a string_view of the current state that is valid for the duration
  // of the call.
  void RequestContent(const ContentProcessFun &processor) const;

  // Same as RequestContent() for a specific line.
  void RequestLine(int line, const ContentProcessFun &processor) const;

  // Apply a single LSP edit operation.
  bool ApplyChange(const TextDocumentContentChangeEvent &c);

  // Apply a sequence of changes.
  void ApplyChanges(const std::vector<TextDocumentContentChangeEvent> &cc);

  // Lines in this document.
  size_t lines() const { return lines_.size(); }

  // Length of document in bytes.
  int64_t document_length() const { return document_length_; }

  // Last global version number this buffer has edited from.
  int64_t last_global_version() const { return last_global_version_; }

  // Set global version; this typically will be done by the BufferCollection.
  void set_last_global_version(int64_t v) { last_global_version_ = v; }

 private:
  // TODO: this should be unique_ptr, but assignment in the insert() command
  // will not work. Needs to be formulated with something something std::move ?
  using LineVector = std::vector<std::shared_ptr<std::string>>;

  static LineVector GenerateLines(absl::string_view content);
  void ReplaceDocument(absl::string_view content);
  bool LineEdit(const TextDocumentContentChangeEvent &c, std::string *str);
  bool MultiLineEdit(const TextDocumentContentChangeEvent &c);

  int64_t last_global_version_ = 0;
  int64_t document_length_ = 0;
  LineVector lines_;
};

// A buffer collection keeps track of various open text buffers on the
// client side. Registers new ExitTextBuffers by subscribing to events
// coming from the client.
class BufferCollection {
 public:
  // Create buffer collection and subscribe to buffer events at the dispatcher.
  explicit BufferCollection(JsonRpcDispatcher *dispatcher);
  BufferCollection(const BufferCollection &) = delete;
  BufferCollection(BufferCollection &&) = delete;

  // Handle textDocument/didOpen event; create a new EditTextBuffer.
  void didOpenEvent(const DidOpenTextDocumentParams &o);

  // Handle textDocument/didChange event. Delegate changes to existing buffer.
  void didChangeEvent(const DidChangeTextDocumentParams &o);

  // Handle textDocument/didClose event. Forget about buffer.
  void didCloseEvent(const DidCloseTextDocumentParams &o);

  const EditTextBuffer *findBufferByUri(const std::string &uri) const {
    auto found = buffers_.find(uri);
    return found == buffers_.end() ? nullptr : found->second.get();
  }

  // Edits done on all buffers from all time. Allows to compare a single
  // number if there is any change since last time. Good to remember to get
  // only changed buffers when calling MapBuffersChangedSince()
  int64_t global_version() const { return global_version_; }

  using UriBufferCallback =
      std::function<void(const std::string &uri, const EditTextBuffer *buffer)>;

  // Set a callback that is called with each change on the buffer collection.
  //
  // If a new buffer has been added or received a change, the callback is
  // called with the uri and a pointer to the buffer.
  // If a buffer has been removed, the uri of the removed buffer
  // and a nullptr will be sent.
  //
  // Note, there can only be one callback at a time, which is sufficient
  // for the current uses; if that changes, need some Add/Remove calls.
  void SetChangeListener(const UriBufferCallback &listener) {
    change_listener_ = listener;
  }

  size_t documents_open() const { return buffers_.size(); }

 private:
  int64_t global_version_ = 0;
  UriBufferCallback change_listener_ = nullptr;
  std::unordered_map<std::string, std::unique_ptr<EditTextBuffer>> buffers_;
};
}  // namespace lsp
}  // namespace verible

#endif  // VERIBLE_COMMON_LSP_LSP_TEXT_BUFFER_H
