/*
 *  Copyright (C) 2010  Giorgio Wicklein <g.wicklein@giowisys.com>
 *
 *  This file is part of DaemonFS.
 *
 *  DaemonFS 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.
 *
 *  DaemonFS 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 a copy of the GNU General Public License
 *  along with DaemonFS.  If not, see <http://www.gnu.org/licenses/>.
 */

//-----------------------------------------------------------------------------
// Hearders
//-----------------------------------------------------------------------------

#include <QFileSystemWatcher>
#include <QDebug>
#include <QDirIterator>
#include <QDateTime>

#include "filewatcherengine.h"


//-----------------------------------------------------------------------------
// Public
//-----------------------------------------------------------------------------

FileWatcherEngine::FileWatcherEngine(QObject *parent) : QObject(parent)
{
    fileSystemWatcher = new QFileSystemWatcher(this);
    fileMap = new QMap<QString, QDateTime>();

    connect(fileSystemWatcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)));
    connect(fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)));
}

FileWatcherEngine::~FileWatcherEngine()
{
    delete fileMap;
}

void FileWatcherEngine::addPaths(QStringList &paths)
{
    QStringList files;

    for (int i = 0; i < paths.size(); i++)
        getAllFiles(paths.at(i), files);

    qDebug() << "[DaemonFS]: Indexed files: " << files.size();

    fileSystemWatcher->addPaths(files);
}

void FileWatcherEngine::clear()
{
    QStringList paths = fileMap->keys();
    fileSystemWatcher->removePaths(paths);
    fileMap->clear();
}

QDateTime FileWatcherEngine::getLastModification(QString path)
{
    //this function is not used for now
    return fileMap->value(path);
}

bool FileWatcherEngine::isDeleted(QString path)
{
    if (fileMap->contains(path)) {
        return (!QFileInfo(path).exists());
    } else
        return false;
}

bool FileWatcherEngine::isNew(QString path)
{
    bool somethingNew = false;

    if (QFileInfo(path).isDir()) {
        QFileInfoList files = QDir(path).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden);
        for (int i = 0; i < files.size(); i++) {
            if (!fileMap->contains(files.at(i).absoluteFilePath())) {
                somethingNew = true;
                fileSystemWatcher->addPath(files.at(i).absoluteFilePath());
                emit addToTableSignal(files.at(i).absoluteFilePath());
            }
        }
        if (somethingNew)
            return true;
        else
            return false;
    }
    else {
        return false;
    }
}

//-----------------------------------------------------------------------------
// Private slots
//-----------------------------------------------------------------------------

void FileWatcherEngine::fileChanged(QString path)
{
    //qDebug() << QString("This file has been changed: ") << path;

    emit fschanged(path);
}

void FileWatcherEngine::dirChanged(QString path)
{
    //qDebug() << QString("This directory has been changed: ") << path;

    emit fschanged(path);
}

//-----------------------------------------------------------------------------
// Private
//-----------------------------------------------------------------------------

void FileWatcherEngine::getAllFiles(QString path, QStringList &result)
{
    QFileInfo file(path);

    if (file.isDir()) {

        // Add top directroy
        fileSystemWatcher->addPath(file.absoluteFilePath());
        fileMap->insert(file.absoluteFilePath(), QFileInfo(file.absoluteFilePath()).lastModified());

        // Add all subfiles and subdirs
        QDirIterator it(path, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden, QDirIterator::Subdirectories);

        while (it.hasNext()) {
            QString tmp = it.next();
            result.append(tmp);
            fileMap->insert(tmp, QFileInfo(tmp).lastModified());
        }

    } else {

        result.append(file.absoluteFilePath());
        fileMap->insert(file.absoluteFilePath(), file.lastModified());

    }
}
