/*
 * This file is part of the KDE Baloo Project
 * Copyright (C) 2015  Pinak Ahuja <pinak.ahuja@gmail.com>
 * Copyright (C) 2015  Vishesh Handa <vhanda@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "monitorcommand.h"
#include "indexerstate.h"

#include <QDBusConnection>
#include <QDBusServiceWatcher>

using namespace Baloo;

MonitorCommand::MonitorCommand(QObject *parent)
    : QObject(parent)
    , m_out(stdout)
    , m_err(stderr)
    , m_indexerDBusInterface(nullptr)
    , m_schedulerDBusInterface(nullptr)
    , m_dbusServiceWatcher(nullptr)

{
    m_dbusServiceWatcher = new QDBusServiceWatcher(
        QStringLiteral("org.kde.baloo"), QDBusConnection::sessionBus()
    );
    connect(m_dbusServiceWatcher, &QDBusServiceWatcher::serviceRegistered,
            this, &MonitorCommand::balooIsAvailable);
    connect(m_dbusServiceWatcher, &QDBusServiceWatcher::serviceUnregistered,
            this, &MonitorCommand::balooIsNotAvailable);

    m_indexerDBusInterface = new org::kde::baloo::fileindexer(QStringLiteral("org.kde.baloo"),
        QStringLiteral("/fileindexer"),
        QDBusConnection::sessionBus(),
        this
    );
    connect(m_indexerDBusInterface, &org::kde::baloo::fileindexer::startedIndexingFile,
        this, &MonitorCommand::startedIndexingFile);
    connect(m_indexerDBusInterface, &org::kde::baloo::fileindexer::finishedIndexingFile,
        this, &MonitorCommand::finishedIndexingFile);

    m_schedulerDBusInterface = new org::kde::baloo::scheduler(QStringLiteral("org.kde.baloo"),
        QStringLiteral("/scheduler"),
        QDBusConnection::sessionBus(),
        this
    );
    connect(m_schedulerDBusInterface, &org::kde::baloo::scheduler::stateChanged,
        this, &MonitorCommand::stateChanged);

    if (m_indexerDBusInterface->isValid() && m_schedulerDBusInterface->isValid()) {
        m_err << i18n("Press ctrl+c to stop monitoring\n");
        m_err.flush();
        balooIsAvailable();
        stateChanged(m_schedulerDBusInterface->state());
        QString currentFile = m_indexerDBusInterface->currentFile();
        if (!currentFile.isEmpty()) {
            startedIndexingFile(currentFile);
        }
    } else {
        balooIsNotAvailable();
    }

    m_dbusServiceWatcher->setWatchMode(QDBusServiceWatcher::WatchForOwnerChange);
}

void MonitorCommand::balooIsNotAvailable()
{
    m_indexerDBusInterface->unregisterMonitor();
    m_err << i18n("Waiting for file indexer to start\n");
    m_err << i18n("Press Ctrl+C to stop monitoring\n");
    m_err.flush();
}

void MonitorCommand::balooIsAvailable()
{
    m_indexerDBusInterface->registerMonitor();
    m_err << i18n("File indexer is running\n");
    m_err.flush();
}

int MonitorCommand::exec(const QCommandLineParser& parser)
{
    Q_UNUSED(parser);
    return QCoreApplication::instance()->exec();
}

void MonitorCommand::startedIndexingFile(const QString& filePath)
{
    m_currentFile = filePath;
    m_out << i18nc("currently indexed file", "Indexing: %1", filePath)
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
          << flush;
#else
          << Qt::flush;
#endif
}

void MonitorCommand::finishedIndexingFile(const QString& filePath)
{
    Q_UNUSED(filePath);

    m_currentFile.clear();
    m_out << i18n(": Ok\n");
    m_out.flush();
}

void MonitorCommand::stateChanged(int state)
{
    m_out << stateString(state) << '\n';
    m_out.flush();
}
