// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "p2p/server/file_watcher.h"

#include <gio/gio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>

#include <base/logging.h>

using std::string;
using std::vector;

using base::FilePath;

namespace p2p {

namespace server {

class FileWatcherGLib : public FileWatcher {
 public:
  FileWatcherGLib(const FilePath& dir, const string& file_extension);

  ~FileWatcherGLib() override;

  const vector<FilePath>& files() const override;

  const FilePath& dir() const override;
  const string& file_extension() const override;

  void SetChangedCallback(FileWatcherCallback changed_callback) override;

  bool Init();

 private:
  // Looks at all files in |dir_| and sees if anything has
  // changed. Usually called from the file monitoring callback from
  // the kernel (inotify via GFileMonitor). The |changed_file|
  // parameter should be NULL unless the kernel indicates the given
  // file has changed. Updates the |files_| member.
  void ReloadDir(const FilePath* changed_file);

  // Used for handling the GFileMonitor::changed GLib signal.
  static void OnMonitorChanged(GFileMonitor* monitor,
                               GFile* file,
                               GFile* other_file,
                               GFileMonitorEvent event_type,
                               gpointer user_data);

  // The directory we monitor.
  FilePath dir_;

  // The file extension for files we are interested in, e.g. ".p2p".
  string file_extension_;

  // The callback set by the user of our callback.
  FileWatcherCallback changed_callback_;

  // The current set of files in |dir_|. Is updated by ReloadDir().
  vector<FilePath> files_;

  // The GLib abstraction used to interface with the kernel's inotify
  // subsystem.
  GFileMonitor* monitor_;

  DISALLOW_COPY_AND_ASSIGN(FileWatcherGLib);
};

const FilePath& FileWatcherGLib::dir() const {
  return dir_;
}

const string& FileWatcherGLib::file_extension() const {
  return file_extension_;
}

void FileWatcherGLib::OnMonitorChanged(GFileMonitor* monitor,
                                       GFile* file,
                                       GFile* other_file,
                                       GFileMonitorEvent event_type,
                                       gpointer user_data) {
  FileWatcherGLib* file_watcher = reinterpret_cast<FileWatcherGLib*>(user_data);

  // Ignore hints
  if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
    return;

  // Ignore files not matching the extension
  gchar* file_name = g_file_get_path(file);
  if (!g_str_has_suffix(file_name, file_watcher->file_extension_.c_str())) {
    g_free(file_name);
    return;
  }

  VLOG(2) << "OnMonitorChanged, event_type=" << event_type
          << " file=" << file_name;
  FilePath path(file_name);
  file_watcher->ReloadDir(&path);
  g_free(file_name);
}

FileWatcherGLib::FileWatcherGLib(const FilePath& dir,
                                 const string& file_extension)
    : dir_(dir), file_extension_(file_extension) {}

bool FileWatcherGLib::Init() {
  GFile* file;
  GError* error = NULL;

  file = g_file_new_for_path(dir_.value().c_str());
  monitor_ = g_file_monitor_directory(file, G_FILE_MONITOR_NONE,
                                      NULL, /* GCancellable */
                                      &error);
  if (monitor_ == NULL) {
    LOG(ERROR) << "Error monitoring directory " << dir_.value() << ": "
               << error->message << "(" << error->code << ", "
               << g_quark_to_string(error->domain) << ")";
    g_clear_error(&error);
    return false;
  } else {
    g_signal_connect(monitor_, "changed", G_CALLBACK(OnMonitorChanged), this);
  }

  ReloadDir(NULL);

  g_clear_object(&file);
  return true;
}

FileWatcherGLib::~FileWatcherGLib() {
  if (monitor_ != NULL) {
    g_signal_handlers_disconnect_by_func(monitor_, (gpointer)OnMonitorChanged,
                                         this);
    g_file_monitor_cancel(monitor_);
    g_clear_object(&monitor_);
  }
}

void FileWatcherGLib::SetChangedCallback(FileWatcherCallback changed_callback) {
  changed_callback_ = changed_callback;
}

static void diff_sorted_vectors(
    const vector<FilePath>::iterator& a_first,
    const vector<FilePath>::iterator& a_last,
    const vector<FilePath>::iterator& b_first,
    const vector<FilePath>::iterator& b_last,
    vector<FilePath>* added,        // in b, not in a
    vector<FilePath>* removed,      // in a, not in b
    vector<FilePath>* unchanged) {  // in both a and b
  vector<FilePath>::const_iterator ai = a_first;
  vector<FilePath>::const_iterator bi = b_first;

  while (ai != a_last && bi != b_last) {
    int order = ai->value().compare(bi->value());
    if (order < 0) {
      // *ai > *bi
      removed->push_back(*ai);
      ++ai;
    } else if (order > 0) {
      // *ai < *bi
      added->push_back(*bi);
      ++bi;
    } else {
      // *ai == *bi
      unchanged->push_back(*bi);
      ++ai;
      ++bi;
    }
  }

  while (ai != a_last) {
    removed->push_back(*ai);
    ++ai;
  }

  while (bi != b_last) {
    added->push_back(*bi);
    ++bi;
  }
}

void FileWatcherGLib::ReloadDir(const FilePath* changed_file) {
  GDir* dir;
  GError* error = NULL;
  const char* name;
  vector<FilePath> new_files;

  VLOG(2) << "in ReloadDir(), dir=" << dir_.value() << "file="
          << (changed_file != NULL ? changed_file->value() : "(none)");

  dir = g_dir_open(dir_.value().c_str(), 0, &error);
  if (dir == NULL) {
    LOG(ERROR) << "Error opening directory " << dir_.value() << ": "
               << error->message << "(" << error->code << ", "
               << g_quark_to_string(error->domain) << ")";
    return;
  }

  while ((name = g_dir_read_name(dir)) != NULL) {
    if (file_extension_.length() > 0 &&
        g_str_has_suffix(name, file_extension_.c_str())) {
      new_files.push_back(dir_.Append(name));
    }
  }
  g_dir_close(dir);

  vector<FilePath> added;
  vector<FilePath> removed;
  vector<FilePath> unchanged;
  std::sort(new_files.begin(), new_files.end());
  // TODO(zeuthen): actually unnecessary to sort files_
  std::sort(files_.begin(), files_.end());
  diff_sorted_vectors(files_.begin(), files_.end(), new_files.begin(),
                      new_files.end(), &added, &removed, &unchanged);
  files_ = new_files;

  if (!changed_callback_.is_null()) {
    for (auto const& i : removed) {
      VLOG(2) << "Emitting kFileRemoved for file " << i.value();
      changed_callback_.Run(i, FileWatcher::EventType::kFileRemoved);
    }
    for (auto const& i : unchanged) {
      if (changed_file != NULL && *changed_file == i) {
        VLOG(2) << "Emitting kFileChanged for file " << i.value();
        changed_callback_.Run(i, FileWatcher::EventType::kFileChanged);
      }
    }
    for (auto const& i : added) {
      VLOG(2) << "Emitting kFileAdded for file " << i.value();
      changed_callback_.Run(i, FileWatcher::EventType::kFileAdded);
    }
  }
}

const vector<FilePath>& FileWatcherGLib::files() const {
  return files_;
}

// -----------------------------------------------------------------------------

FileWatcher* FileWatcher::Construct(const FilePath& dir,
                                    const string& file_extension) {
  FileWatcherGLib* instance = new FileWatcherGLib(dir, file_extension);
  if (!instance->Init()) {
    delete instance;
    return NULL;
  }
  return instance;
}

}  // namespace server

}  // namespace p2p
