/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmFileMonitor.h"

#include <cassert>
#include <cstddef>
#include <unordered_map>
#include <utility>

#include "cmsys/SystemTools.hxx"

#include "cmAlgorithms.h"

namespace {
void on_directory_change(uv_fs_event_t* handle, const char* filename,
                         int events, int status);
void on_fs_close(uv_handle_t* handle);
} // namespace

class cmIBaseWatcher
{
public:
  virtual ~cmIBaseWatcher() = default;

  virtual void Trigger(const std::string& pathSegment, int events,
                       int status) const = 0;
  virtual std::string Path() const = 0;
  virtual uv_loop_t* Loop() const = 0;

  virtual void StartWatching() = 0;
  virtual void StopWatching() = 0;

  virtual std::vector<std::string> WatchedFiles() const = 0;
  virtual std::vector<std::string> WatchedDirectories() const = 0;
};

class cmVirtualDirectoryWatcher : public cmIBaseWatcher
{
public:
  ~cmVirtualDirectoryWatcher() override { cmDeleteAll(this->Children); }

  cmIBaseWatcher* Find(const std::string& ps)
  {
    const auto i = this->Children.find(ps);
    return (i == this->Children.end()) ? nullptr : i->second;
  }

  void Trigger(const std::string& pathSegment, int events,
               int status) const final
  {
    if (pathSegment.empty()) {
      for (auto const& child : this->Children) {
        child.second->Trigger(std::string(), events, status);
      }
    } else {
      const auto i = this->Children.find(pathSegment);
      if (i != this->Children.end()) {
        i->second->Trigger(std::string(), events, status);
      }
    }
  }

  void StartWatching() override
  {
    for (auto const& child : this->Children) {
      child.second->StartWatching();
    }
  }

  void StopWatching() override
  {
    for (auto const& child : this->Children) {
      child.second->StopWatching();
    }
  }

  std::vector<std::string> WatchedFiles() const final
  {
    std::vector<std::string> result;
    for (auto const& child : this->Children) {
      for (std::string const& f : child.second->WatchedFiles()) {
        result.push_back(f);
      }
    }
    return result;
  }

  std::vector<std::string> WatchedDirectories() const override
  {
    std::vector<std::string> result;
    for (auto const& child : this->Children) {
      for (std::string const& dir : child.second->WatchedDirectories()) {
        result.push_back(dir);
      }
    }
    return result;
  }

  void Reset()
  {
    cmDeleteAll(this->Children);
    this->Children.clear();
  }

  void AddChildWatcher(const std::string& ps, cmIBaseWatcher* watcher)
  {
    assert(!ps.empty());
    assert(this->Children.find(ps) == this->Children.end());
    assert(watcher);

    this->Children.emplace(std::make_pair(ps, watcher));
  }

private:
  std::unordered_map<std::string, cmIBaseWatcher*> Children; // owned!
};

// Root of all the different (on windows!) root directories:
class cmRootWatcher : public cmVirtualDirectoryWatcher
{
public:
  cmRootWatcher(uv_loop_t* loop)
    : mLoop(loop)
  {
    assert(loop);
  }

  std::string Path() const final
  {
    assert(false);
    return std::string();
  }
  uv_loop_t* Loop() const final { return this->mLoop; }

private:
  uv_loop_t* const mLoop; // no ownership!
};

// Real directories:
class cmRealDirectoryWatcher : public cmVirtualDirectoryWatcher
{
public:
  cmRealDirectoryWatcher(cmVirtualDirectoryWatcher* p, const std::string& ps)
    : Parent(p)
    , PathSegment(ps)
  {
    assert(p);
    assert(!ps.empty());

    p->AddChildWatcher(ps, this);
  }

  void StartWatching() final
  {
    if (!this->Handle) {
      this->Handle = new uv_fs_event_t;

      uv_fs_event_init(this->Loop(), this->Handle);
      this->Handle->data = this;
      uv_fs_event_start(this->Handle, &on_directory_change, Path().c_str(), 0);
    }
    cmVirtualDirectoryWatcher::StartWatching();
  }

  void StopWatching() final
  {
    if (this->Handle) {
      uv_fs_event_stop(this->Handle);
      if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(this->Handle))) {
        uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
      }
      this->Handle = nullptr;
    }
    cmVirtualDirectoryWatcher::StopWatching();
  }

  uv_loop_t* Loop() const final { return this->Parent->Loop(); }

  std::vector<std::string> WatchedDirectories() const override
  {
    std::vector<std::string> result = { Path() };
    for (std::string const& dir :
         cmVirtualDirectoryWatcher::WatchedDirectories()) {
      result.push_back(dir);
    }
    return result;
  }

protected:
  cmVirtualDirectoryWatcher* const Parent;
  const std::string PathSegment;

private:
  uv_fs_event_t* Handle = nullptr; // owner!
};

// Root directories:
class cmRootDirectoryWatcher : public cmRealDirectoryWatcher
{
public:
  cmRootDirectoryWatcher(cmRootWatcher* p, const std::string& ps)
    : cmRealDirectoryWatcher(p, ps)
  {
  }

  std::string Path() const final { return this->PathSegment; }
};

// Normal directories below root:
class cmDirectoryWatcher : public cmRealDirectoryWatcher
{
public:
  cmDirectoryWatcher(cmRealDirectoryWatcher* p, const std::string& ps)
    : cmRealDirectoryWatcher(p, ps)
  {
  }

  std::string Path() const final
  {
    return this->Parent->Path() + this->PathSegment + "/";
  }
};

class cmFileWatcher : public cmIBaseWatcher
{
public:
  cmFileWatcher(cmRealDirectoryWatcher* p, const std::string& ps,
                cmFileMonitor::Callback cb)
    : Parent(p)
    , PathSegment(ps)
    , CbList({ std::move(cb) })
  {
    assert(p);
    assert(!ps.empty());
    p->AddChildWatcher(ps, this);
  }

  void StartWatching() final {}

  void StopWatching() final {}

  void AppendCallback(cmFileMonitor::Callback const& cb)
  {
    this->CbList.push_back(cb);
  }

  std::string Path() const final
  {
    return this->Parent->Path() + this->PathSegment;
  }

  std::vector<std::string> WatchedDirectories() const final { return {}; }

  std::vector<std::string> WatchedFiles() const final
  {
    return { this->Path() };
  }

  void Trigger(const std::string& ps, int events, int status) const final
  {
    assert(ps.empty());
    assert(status == 0);
    static_cast<void>(ps);

    const std::string path = this->Path();
    for (cmFileMonitor::Callback const& cb : this->CbList) {
      cb(path, events, status);
    }
  }

  uv_loop_t* Loop() const final { return this->Parent->Loop(); }

private:
  cmRealDirectoryWatcher* Parent;
  const std::string PathSegment;
  std::vector<cmFileMonitor::Callback> CbList;
};

namespace {

void on_directory_change(uv_fs_event_t* handle, const char* filename,
                         int events, int status)
{
  const cmIBaseWatcher* const watcher =
    static_cast<const cmIBaseWatcher*>(handle->data);
  const std::string pathSegment(filename ? filename : "");
  watcher->Trigger(pathSegment, events, status);
}

void on_fs_close(uv_handle_t* handle)
{
  delete reinterpret_cast<uv_fs_event_t*>(handle);
}

} // namespace

cmFileMonitor::cmFileMonitor(uv_loop_t* l)
  : Root(new cmRootWatcher(l))
{
}

cmFileMonitor::~cmFileMonitor()
{
  delete this->Root;
}

void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths,
                                 Callback const& cb)
{
  for (std::string const& p : paths) {
    std::vector<std::string> pathSegments;
    cmsys::SystemTools::SplitPath(p, pathSegments, true);
    const bool pathIsFile = !cmsys::SystemTools::FileIsDirectory(p);

    const size_t segmentCount = pathSegments.size();
    if (segmentCount < 2) { // Expect at least rootdir and filename
      continue;
    }
    cmVirtualDirectoryWatcher* currentWatcher = this->Root;
    for (size_t i = 0; i < segmentCount; ++i) {
      assert(currentWatcher);

      const bool fileSegment = (i == segmentCount - 1 && pathIsFile);
      const bool rootSegment = (i == 0);
      assert(
        !(fileSegment &&
          rootSegment)); // Can not be both filename and root part of the path!

      const std::string& currentSegment = pathSegments[i];
      if (currentSegment.empty()) {
        continue;
      }

      cmIBaseWatcher* nextWatcher = currentWatcher->Find(currentSegment);
      if (!nextWatcher) {
        if (rootSegment) { // Root part
          assert(currentWatcher == this->Root);
          nextWatcher = new cmRootDirectoryWatcher(this->Root, currentSegment);
          assert(currentWatcher->Find(currentSegment) == nextWatcher);
        } else if (fileSegment) { // File part
          assert(currentWatcher != this->Root);
          nextWatcher = new cmFileWatcher(
            dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
            currentSegment, cb);
          assert(currentWatcher->Find(currentSegment) == nextWatcher);
        } else { // Any normal directory in between
          nextWatcher = new cmDirectoryWatcher(
            dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
            currentSegment);
          assert(currentWatcher->Find(currentSegment) == nextWatcher);
        }
      } else {
        if (fileSegment) {
          auto filePtr = dynamic_cast<cmFileWatcher*>(nextWatcher);
          assert(filePtr);
          filePtr->AppendCallback(cb);
          continue;
        }
      }
      currentWatcher = dynamic_cast<cmVirtualDirectoryWatcher*>(nextWatcher);
    }
  }
  this->Root->StartWatching();
}

void cmFileMonitor::StopMonitoring()
{
  this->Root->StopWatching();
  this->Root->Reset();
}

std::vector<std::string> cmFileMonitor::WatchedFiles() const
{
  std::vector<std::string> result;
  if (this->Root) {
    result = this->Root->WatchedFiles();
  }
  return result;
}

std::vector<std::string> cmFileMonitor::WatchedDirectories() const
{
  std::vector<std::string> result;
  if (this->Root) {
    result = this->Root->WatchedDirectories();
  }
  return result;
}
