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