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

#ifndef P2P_SERVER_FAKE_FILE_WATCHER_H_
#define P2P_SERVER_FAKE_FILE_WATCHER_H_

#include <glib.h>

#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/compiler_specific.h>
#include <base/files/file_util.h>

#include "p2p/server/file_watcher.h"

namespace p2p {

namespace server {

// A FileWatcher that doesn't really do anything.
class FakeFileWatcher : public FileWatcher {
 public:
  FakeFileWatcher(const base::FilePath& dir, const std::string& file_extension)
      : dir_(dir), file_extension_(file_extension), source_id_(0) {}

  ~FakeFileWatcher() override {
    if (source_id_ != 0)
      g_source_remove(source_id_);
  }

  const std::vector<base::FilePath>& files() const override {
    return exposed_files_;
  }

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

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

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

  // Fake methods.

  // Add, Remove or Touch a file in the watched directory. Since those
  // functions are intended to be called by a test, the file extension is not
  // checked. This will make the watched directory to emit a call to the
  // provided callback with the appropriate arguments in each case from the main
  // loop.
  bool AddFile(const base::FilePath& filename, size_t file_size) {
    if (files_.find(filename) != files_.end())
      return false;
    files_.insert(filename);

    // Schedule the action.
    if (pending_actions_.empty())
      source_id_ = g_idle_add(OnFileChanged, this);
    pending_actions_.push((FileEvent){.filename = filename,
                                      .event_type = kFileAdded,
                                      .file_size = file_size});
    return true;
  }

  bool RemoveFile(const base::FilePath& filename) {
    if (files_.find(filename) == files_.end())
      return false;
    files_.erase(filename);

    // Schedule the action.
    if (pending_actions_.empty())
      source_id_ = g_idle_add(OnFileChanged, this);
    pending_actions_.push((FileEvent){
        .filename = filename, .event_type = kFileRemoved, .file_size = 0});
    return true;
  }

  bool TouchFile(const base::FilePath& filename, size_t file_size) {
    if (files_.find(filename) != files_.end())
      return false;

    // Schedule the action.
    if (pending_actions_.empty())
      source_id_ = g_idle_add(OnFileChanged, this);
    pending_actions_.push((FileEvent){.filename = filename,
                                      .event_type = kFileChanged,
                                      .file_size = file_size});
    return true;
  }

 private:
  static gboolean OnFileChanged(gpointer user_data) {
    FakeFileWatcher* watcher = reinterpret_cast<FakeFileWatcher*>(user_data);
    const FileEvent& event = watcher->pending_actions_.front();
    char* buf = NULL;

    switch (event.event_type) {
      case kFileAdded:
        watcher->exposed_files_.push_back(event.filename);
        // Create the file on disk to allow the consumer get its file size.
        FALLTHROUGH;
      case kFileChanged:
        // Both kFileAdded and kFileChanged execute this part:
        buf = static_cast<char*>(malloc(event.file_size));
        base::WriteFile(event.filename, buf, event.file_size);
        free(buf);
        break;
      case kFileRemoved:
        watcher->exposed_files_.erase(find(watcher->exposed_files_.begin(),
                                           watcher->exposed_files_.end(),
                                           event.filename));
        unlink(event.filename.value().c_str());
        break;
    }

    // Dispatch the callback. This could add more events to the queue, so we
    // keep the processed event until the callback returns and check empty()
    // later on this function.
    if (!watcher->changed_callback_.is_null())
      watcher->changed_callback_.Run(event.filename, event.event_type);

    watcher->pending_actions_.pop();
    return !watcher->pending_actions_.empty();
  }

  base::FilePath dir_;
  std::string file_extension_;
  FileWatcher::FileWatcherCallback changed_callback_;

  // The list of files in the watched directory once the Add/Remove event was
  // processed. This is what a call to files() will return.
  std::vector<base::FilePath> exposed_files_;

  // The set of files added by the test, used to ensure proper call arguments
  // (i.e. fail when the test attempts to add twice the same file).
  std::set<base::FilePath> files_;

  // The list of pending actions (Add/Remove/Touch) to be processed.
  struct FileEvent {
    base::FilePath filename;
    EventType event_type;
    size_t file_size;
  };
  std::queue<FileEvent> pending_actions_;

  // The source_id used to dispatch file events.
  guint source_id_;

  DISALLOW_COPY_AND_ASSIGN(FakeFileWatcher);
};

}  // namespace server

}  // namespace p2p

#endif  // P2P_SERVER_FAKE_FILE_WATCHER_H_
