//===--- IndexDataStore.cpp - Index data store info -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Index/IndexDataStore.h"
#include "clang/DirectoryWatcher/DirectoryWatcher.h"
#include "../lib/Index/IndexDataStoreUtils.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::index;
using namespace clang::index::store;
using namespace llvm;

namespace {

class UnitEventHandlerData {
  mutable sys::Mutex Mtx;
  IndexDataStore::UnitEventHandler Handler;

public:
  void setHandler(IndexDataStore::UnitEventHandler handler) {
    sys::ScopedLock L(Mtx);
    Handler = std::move(handler);
  }
  IndexDataStore::UnitEventHandler getHandler() const {
    sys::ScopedLock L(Mtx);
    return Handler;
  }
};

class IndexDataStoreImpl {
  std::string FilePath;
  std::shared_ptr<UnitEventHandlerData> TheUnitEventHandlerData;
  std::unique_ptr<DirectoryWatcher> DirWatcher;

public:
  explicit IndexDataStoreImpl(StringRef indexStorePath)
    : FilePath(indexStorePath) {
    TheUnitEventHandlerData = std::make_shared<UnitEventHandlerData>();
  }

  StringRef getFilePath() const { return FilePath; }
  bool foreachUnitName(bool sorted,
                       llvm::function_ref<bool(StringRef unitName)> receiver);
  void setUnitEventHandler(IndexDataStore::UnitEventHandler Handler);
  bool startEventListening(bool waitInitialSync, std::string &Error);
  void stopEventListening();
  void discardUnit(StringRef UnitName);
  void discardRecord(StringRef RecordName);
  void purgeStaleData();
};

} // anonymous namespace

bool IndexDataStoreImpl::foreachUnitName(bool sorted,
                        llvm::function_ref<bool(StringRef unitName)> receiver) {
  SmallString<128> UnitPath;
  UnitPath = FilePath;
  appendUnitSubDir(UnitPath);

  std::vector<std::string> filenames;

  std::error_code EC;
  for (auto It = sys::fs::directory_iterator(UnitPath, EC),
           End = sys::fs::directory_iterator();
       !EC && It != End; It.increment(EC)) {
    StringRef unitName = sys::path::filename(It->path());
    if (!sorted) {
      if (!receiver(unitName))
        return false;
    } else {
      filenames.push_back(unitName);
    }
  }

  if (sorted) {
    std::sort(filenames.begin(), filenames.end());
    for (auto &fname : filenames)
      if (!receiver(fname))
        return false;
  }
  return true;
}

void IndexDataStoreImpl::setUnitEventHandler(IndexDataStore::UnitEventHandler handler) {
  TheUnitEventHandlerData->setHandler(std::move(handler));
}

bool IndexDataStoreImpl::startEventListening(bool waitInitialSync, std::string &Error) {
  if (DirWatcher) {
    Error = "event listener already active";
    return true;
  }

  SmallString<128> UnitPath;
  UnitPath = FilePath;
  appendUnitSubDir(UnitPath);

  auto localUnitEventHandlerData = TheUnitEventHandlerData;
  auto OnUnitsChange = [localUnitEventHandlerData](ArrayRef<DirectoryWatcher::Event> Events, bool isInitial) {
    SmallVector<IndexDataStore::UnitEvent, 16> UnitEvents;
    UnitEvents.reserve(Events.size());
    for (const DirectoryWatcher::Event &evt : Events) {
      IndexDataStore::UnitEventKind K;
      StringRef UnitName = sys::path::filename(evt.Filename);
      switch (evt.Kind) {
      case DirectoryWatcher::EventKind::Added:
        K = IndexDataStore::UnitEventKind::Added; break;
      case DirectoryWatcher::EventKind::Removed:
        K = IndexDataStore::UnitEventKind::Removed; break;
      case DirectoryWatcher::EventKind::Modified:
        K = IndexDataStore::UnitEventKind::Modified; break;
      case DirectoryWatcher::EventKind::DirectoryDeleted:
        K = IndexDataStore::UnitEventKind::DirectoryDeleted;
        UnitName = StringRef();
        break;
      }
      UnitEvents.push_back(IndexDataStore::UnitEvent{K, UnitName, evt.ModTime});
    }

    if (auto handler = localUnitEventHandlerData->getHandler()) {
      IndexDataStore::UnitEventNotification EventNote{isInitial, UnitEvents};
      handler(EventNote);
    }
  };

  DirWatcher = DirectoryWatcher::create(UnitPath.str(), OnUnitsChange,
                                        waitInitialSync, Error);
  if (!DirWatcher)
    return true;

  return false;
}

void IndexDataStoreImpl::stopEventListening() {
  DirWatcher.reset();
}

void IndexDataStoreImpl::discardUnit(StringRef UnitName) {
  SmallString<128> UnitPath;
  UnitPath = FilePath;
  appendUnitSubDir(UnitPath);
  appendInteriorUnitPath(UnitName, UnitPath);
  sys::fs::remove(UnitPath);
}

void IndexDataStoreImpl::discardRecord(StringRef RecordName) {
  SmallString<128> RecordPath;
  RecordPath = FilePath;
  appendRecordSubDir(RecordPath);
  appendInteriorRecordPath(RecordName, RecordPath);
  sys::fs::remove(RecordPath);
}

void IndexDataStoreImpl::purgeStaleData() {
  // FIXME: Implement.
}


std::unique_ptr<IndexDataStore>
IndexDataStore::create(StringRef IndexStorePath, std::string &Error) {
  if (!sys::fs::exists(IndexStorePath)) {
    raw_string_ostream OS(Error);
    OS << "index store path does not exist: " << IndexStorePath;
    return nullptr;
  }

  return std::unique_ptr<IndexDataStore>(
    new IndexDataStore(new IndexDataStoreImpl(IndexStorePath)));
}

#define IMPL static_cast<IndexDataStoreImpl*>(Impl)

IndexDataStore::~IndexDataStore() {
  delete IMPL;
}

StringRef IndexDataStore::getFilePath() const {
  return IMPL->getFilePath();
}

bool IndexDataStore::foreachUnitName(bool sorted,
                     llvm::function_ref<bool(StringRef unitName)> receiver) {
  return IMPL->foreachUnitName(sorted, std::move(receiver));
}

unsigned IndexDataStore::getFormatVersion() {
  return STORE_FORMAT_VERSION;
}

void IndexDataStore::setUnitEventHandler(UnitEventHandler Handler) {
  return IMPL->setUnitEventHandler(std::move(Handler));
}

bool IndexDataStore::startEventListening(bool waitInitialSync, std::string &Error) {
  return IMPL->startEventListening(waitInitialSync, Error);
}

void IndexDataStore::stopEventListening() {
  return IMPL->stopEventListening();
}

void IndexDataStore::discardUnit(StringRef UnitName) {
  IMPL->discardUnit(UnitName);
}

void IndexDataStore::discardRecord(StringRef RecordName) {
  IMPL->discardRecord(RecordName);
}

void IndexDataStore::purgeStaleData() {
  IMPL->purgeStaleData();
}
