//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DraftStore.h"
#include "SourceCode.h"
#include "llvm/Support/Errc.h"

using namespace clang;
using namespace clang::clangd;

llvm::Optional<std::string> DraftStore::getDraft(PathRef File) const {
  std::lock_guard<std::mutex> Lock(Mutex);

  auto It = Drafts.find(File);
  if (It == Drafts.end())
    return llvm::None;

  return It->second;
}

std::vector<Path> DraftStore::getActiveFiles() const {
  std::lock_guard<std::mutex> Lock(Mutex);
  std::vector<Path> ResultVector;

  for (auto DraftIt = Drafts.begin(); DraftIt != Drafts.end(); DraftIt++)
    ResultVector.push_back(DraftIt->getKey());

  return ResultVector;
}

void DraftStore::addDraft(PathRef File, StringRef Contents) {
  std::lock_guard<std::mutex> Lock(Mutex);

  Drafts[File] = Contents;
}

llvm::Expected<std::string> DraftStore::updateDraft(
    PathRef File, llvm::ArrayRef<TextDocumentContentChangeEvent> Changes) {
  std::lock_guard<std::mutex> Lock(Mutex);

  auto EntryIt = Drafts.find(File);
  if (EntryIt == Drafts.end()) {
    return llvm::make_error<llvm::StringError>(
        "Trying to do incremental update on non-added document: " + File,
        llvm::errc::invalid_argument);
  }

  std::string Contents = EntryIt->second;

  for (const TextDocumentContentChangeEvent &Change : Changes) {
    if (!Change.range) {
      Contents = Change.text;
      continue;
    }

    const Position &Start = Change.range->start;
    llvm::Expected<size_t> StartIndex =
        positionToOffset(Contents, Start, false);
    if (!StartIndex)
      return StartIndex.takeError();

    const Position &End = Change.range->end;
    llvm::Expected<size_t> EndIndex = positionToOffset(Contents, End, false);
    if (!EndIndex)
      return EndIndex.takeError();

    if (*EndIndex < *StartIndex)
      return llvm::make_error<llvm::StringError>(
          llvm::formatv(
              "Range's end position ({0}) is before start position ({1})", End,
              Start),
          llvm::errc::invalid_argument);

    if (Change.rangeLength &&
        (ssize_t)(*EndIndex - *StartIndex) != *Change.rangeLength)
      return llvm::make_error<llvm::StringError>(
          llvm::formatv("Change's rangeLength ({0}) doesn't match the "
                        "computed range length ({1}).",
                        *Change.rangeLength, *EndIndex - *StartIndex),
          llvm::errc::invalid_argument);

    std::string NewContents;
    NewContents.reserve(*StartIndex + Change.text.length() +
                        (Contents.length() - *EndIndex));

    NewContents = Contents.substr(0, *StartIndex);
    NewContents += Change.text;
    NewContents += Contents.substr(*EndIndex);

    Contents = std::move(NewContents);
  }

  EntryIt->second = Contents;
  return Contents;
}

void DraftStore::removeDraft(PathRef File) {
  std::lock_guard<std::mutex> Lock(Mutex);

  Drafts.erase(File);
}
