/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2016, Regents of the University of California.
 *
 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
 *
 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received copies of the GNU General Public License along with
 * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
 */
#include "fs-watcher.hpp"
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
#include <QtGui>
#include <fstream>
#include <set>

using namespace std;
using namespace boost;
namespace fs = boost::filesystem;

BOOST_AUTO_TEST_SUITE(TestFsWatcher)

void
onChange(set<string>& files, const fs::path& file)
{
  cerr << "onChange called" << endl;
  files.insert(file.string());
}

void
onDelete(set<string>& files, const fs::path& file)
{
  files.erase(file.string());
}

void
create_file(const fs::path& ph, const std::string& contents)
{
  std::ofstream f(ph.string().c_str());
  if (!f) {
    abort();
  }
  if (!contents.empty()) {
    f << contents;
  }
}

void
run(fs::path dir, FsWatcher::LocalFile_Change_Callback c, FsWatcher::LocalFile_Change_Callback d)
{
  int x = 0;
  QCoreApplication app(x, 0);
  FsWatcher watcher(dir.string().c_str(), c, d);
  app.exec();
  sleep(100);
}

BOOST_AUTO_TEST_CASE(TestFsWatcher)
{
  fs::path dir = fs::absolute(fs::path("TestFsWatcher"));
  if (fs::exists(dir)) {
    fs::remove_all(dir);
  }

  fs::create_directory(dir);

  set<string> files;

  FsWatcher::LocalFile_Change_Callback fileChange = boost::bind(onChange, ref(files), _1);
  FsWatcher::LocalFile_Change_Callback fileDelete = boost::bind(onDelete, ref(files), _1);

  thread workThread(run, dir, fileChange, fileDelete);
  //FsWatcher watcher (dir.string().c_str(), fileChange, fileDelete);

  // ============ check create file detection ================
  create_file(dir / "test.txt", "hello");
  // have to at least wait 0.5 seconds
  usleep(1000000);
  // test.txt
  BOOST_CHECK_EQUAL(files.size(), 1);
  BOOST_CHECK(files.find("test.txt") != files.end());

  // =========== check create a bunch of files in sub dir =============
  fs::path subdir = dir / "sub";
  fs::create_directory(subdir);
  for (int i = 0; i < 10; i++) {
    string filename = boost::lexical_cast<string>(i);
    create_file(subdir / filename.c_str(), boost::lexical_cast<string>(i));
  }
  // have to at least wait 0.5 * 2 seconds
  usleep(1100000);
  // test.txt
  // sub/0..9
  BOOST_CHECK_EQUAL(files.size(), 11);
  for (int i = 0; i < 10; i++) {
    string filename = boost::lexical_cast<string>(i);
    BOOST_CHECK(files.find("sub/" + filename) != files.end());
  }

  // ============== check copy directory with files to two levels of sub dirs =================
  fs::create_directory(dir / "sub1");
  fs::path subdir1 = dir / "sub1" / "sub2";
  fs::copy_directory(subdir, subdir1);
  for (int i = 0; i < 5; i++) {
    string filename = boost::lexical_cast<string>(i);
    fs::copy_file(subdir / filename.c_str(), subdir1 / filename.c_str());
  }
  // have to at least wait 0.5 * 2 seconds
  usleep(1100000);
  // test.txt
  // sub/0..9
  // sub1/sub2/0..4
  BOOST_CHECK_EQUAL(files.size(), 16);
  for (int i = 0; i < 5; i++) {
    string filename = boost::lexical_cast<string>(i);
    BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
  }

  // =============== check remove files =========================
  for (int i = 0; i < 7; i++) {
    string filename = boost::lexical_cast<string>(i);
    fs::remove(subdir / filename.c_str());
  }
  usleep(1100000);
  // test.txt
  // sub/7..9
  // sub1/sub2/0..4
  BOOST_CHECK_EQUAL(files.size(), 9);
  for (int i = 0; i < 10; i++) {
    string filename = boost::lexical_cast<string>(i);
    if (i < 7)
      BOOST_CHECK(files.find("sub/" + filename) == files.end());
    else
      BOOST_CHECK(files.find("sub/" + filename) != files.end());
  }

  // =================== check remove files again, remove the whole dir this time ===================
  // before remove check
  for (int i = 0; i < 5; i++) {
    string filename = boost::lexical_cast<string>(i);
    BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
  }
  fs::remove_all(subdir1);
  usleep(1100000);
  BOOST_CHECK_EQUAL(files.size(), 4);
  // test.txt
  // sub/7..9
  for (int i = 0; i < 5; i++) {
    string filename = boost::lexical_cast<string>(i);
    BOOST_CHECK(files.find("sub1/sub2/" + filename) == files.end());
  }

  // =================== check rename files =======================
  for (int i = 7; i < 10; i++) {
    string filename = boost::lexical_cast<string>(i);
    fs::rename(subdir / filename.c_str(), dir / filename.c_str());
  }
  usleep(1100000);
  // test.txt
  // 7
  // 8
  // 9
  // sub
  BOOST_CHECK_EQUAL(files.size(), 4);
  for (int i = 7; i < 10; i++) {
    string filename = boost::lexical_cast<string>(i);
    BOOST_CHECK(files.find("sub/" + filename) == files.end());
    BOOST_CHECK(files.find(filename) != files.end());
  }

  create_file(dir / "add-removal-check.txt", "add-removal-check");
  usleep(1200000);
  BOOST_CHECK(files.find("add-removal-check.txt") != files.end());

  fs::remove(dir / "add-removal-check.txt");
  usleep(1200000);
  BOOST_CHECK(files.find("add-removal-check.txt") == files.end());

  create_file(dir / "add-removal-check.txt", "add-removal-check");
  usleep(1200000);
  BOOST_CHECK(files.find("add-removal-check.txt") != files.end());

  fs::remove(dir / "add-removal-check.txt");
  usleep(1200000);
  BOOST_CHECK(files.find("add-removal-check.txt") == files.end());

  create_file(dir / "add-removal-check.txt", "add-removal-check");
  usleep(1200000);
  BOOST_CHECK(files.find("add-removal-check.txt") != files.end());

  fs::remove(dir / "add-removal-check.txt");
  usleep(1200000);
  BOOST_CHECK(files.find("add-removal-check.txt") == files.end());

  // cleanup
  if (fs::exists(dir)) {
    fs::remove_all(dir);
  }
}

BOOST_AUTO_TEST_SUITE_END()
