/*******************************************************************************
**
** SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru>
** SPDX-License-Identifier: BSD-3-Clause
** This file is part of the OfficeViewer project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
**   this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
**   this list of conditions and the following disclaimer
**   in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
**   may be used to endorse or promote products derived from this software
**   without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/



#include "trackerdocumentprovider.h"
#include "documentlistmodel.h"

#include <QDir>
#include <QProcess>
#include <QDebug>
#include <QtCore/QModelIndex>
#include <QtCore/qthreadpool.h>
#include <QStandardPaths>

#include <qglobal.h>

//#include <QSparqlConnection>
//#include <QSparqlError>
//#include <QSparqlResult>

//#include "config.h"

//The Tracker driver to use. direct = libtracker-sparql based
static const QString trackerDriver{"QTRACKER_DIRECT"};

//The query to run to get files out of Tracker.
static const QString documentQuery{"SELECT ?name ?path ?size ?lastAccessed ?lastModified ?mimeType "
                                   "WHERE {"
                                   "  GRAPH tracker:Documents {"
                                   "    SELECT nfo:fileName(?path) AS ?name"
                                   "      nfo:fileSize(?path) AS ?size"
                                   "      nfo:fileLastAccessed(?path) AS ?lastAccessed"
                                   "      nfo:fileLastModified(?path) AS ?lastModified"
                                   "      ?path ?mimeType"
                                   "    WHERE {"
                                   "      ?u nie:isStoredAs ?path ."
                                   "      ?u nie:mimeType ?mimeType ."
                                   "      { ?u a nfo:PaginatedTextDocument . }"
                                   "      UNION { ?u nie:mimeType 'text/plain' FILTER(fn:ends-with(nfo:fileName(nie:isStoredAs(?u)),'.txt')) }"
                                   "      FILTER (?mimeType IN (%1))"
                                   "      GRAPH tracker:FileSystem {"
                                   "        ?path nie:dataSource ?dataSource ."
                                   "        ?dataSource tracker:available true ."
                                   "        ?path tracker:hidden false ."
                                   "        ?path tracker:rootHidden false"
                                   "      }"
                                   "    }"
                                   "  }"
                                   "}"};

static const QString documentGraph("http://tracker.api.gnome.org/ontology/v3/tracker#Documents");
static const QString supportMimeTypes(SUPPORT_MIMETYPES);

class TrackerDocumentProvider::Private
{
public:
    Private()
        : model(new DocumentListModel)
//        , connection{nullptr}
        , ready(false)
    {
        model->setObjectName("TrackerDocumentList");
    }

    ~Private() { model->deleteLater(); }

    DocumentListModel *model;
//    QSparqlConnection *connection;
    bool ready;
};

TrackerDocumentProvider::TrackerDocumentProvider(QObject *parent)
    : DocumentProvider(parent)
    , d(new Private)
{}

TrackerDocumentProvider::~TrackerDocumentProvider()
{
//    delete d->connection;
    delete d;
}

void TrackerDocumentProvider::classBegin() {}

void TrackerDocumentProvider::componentComplete()
{
//    d->connection = new QSparqlConnection(trackerDriver);
//    connect(d->model, SIGNAL(fileDeleted(QString)), this, SIGNAL(fileDeleted(QString)));
//    if (!d->connection->isValid()) {
//        qWarning() << "No valid QSparqlConnection on TrackerDocumentProvider";
//    } else {
//        startSearch();
//        d->connection->subscribeToGraph(documentGraph);
//        connect(d->connection, &QSparqlConnection::graphUpdated, this, &TrackerDocumentProvider::trackerGraphChanged);
//    }
    qDebug() << "componentComplete";
    startSearch();
}

void TrackerDocumentProvider::startSearch()
{
//    QString supportMimeTypesSparql = QString("'" + supportMimeTypes + "'").split(",").join("', '");
//    QSparqlQuery q(documentQuery.arg(supportMimeTypesSparql));
//    QSparqlResult *result = d->connection->exec(q);
//    if (result->hasError()) {
//        qWarning() << "Error executing sparql query:" << result->lastError();
//        delete result;
//    } else {
//        connect(result, SIGNAL(finished()), this, SLOT(searchFinished()));
//    }
    searchFinished();
}

void TrackerDocumentProvider::stopSearch() {}

QString TrackerDocumentProvider::getMimeType( QString filePath ) {
    return QMimeDatabase().mimeTypeForFile( filePath ).name();
}

int TrackerDocumentProvider::getFileSize( QString filePath ) {
    QFile myFile(filePath);
    return myFile.size();
}
void TrackerDocumentProvider::searchFinished()
{
    d->model->setAllItemsDirty(true);
    QDir directory(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
    qDebug() << "Scanning for files in the" << directory.absolutePath() << "directory...";
    QStringList types = QString(SUPPORT_MIMETYPES).split(",");
    for (QString filename : directory.entryList(QDir::Files)) {
        QString mimeType = getMimeType(filename);
        if (types.contains(mimeType)) {
            QFileInfo file(filename);
            d->model->addItem(file.fileName(),
                              directory.absoluteFilePath(filename),
                              file.suffix(),
                              getFileSize(directory.absoluteFilePath(filename)),
                              file.lastRead(),
                              mimeType);
        }
    }
    // Remove all entries with the dirty mark.
    d->model->removeItemsDirty();
    if (!d->ready) {
        d->ready = true;
        emit readyChanged();
    }
    emit countChanged();
}

int TrackerDocumentProvider::count() const
{
    // TODO lolnope
    return d->model->rowCount(QModelIndex());
}

QString TrackerDocumentProvider::description() const
{
    //: Description for local device files provider
    //% "Files found on this device."
    return qtTrId("docviewer-la-localfiles_description");
}

QUrl TrackerDocumentProvider::icon() const
{
    return QUrl();
}

bool TrackerDocumentProvider::isReady() const
{
    return d->ready;
}

QObject *TrackerDocumentProvider::model() const
{
    return d->model;
}

QUrl TrackerDocumentProvider::thumbnail() const
{
    return QUrl();
}

QString TrackerDocumentProvider::title() const
{
    //: Title for local device files provider
    //% "This Device"
    return qtTrId("docviewer-he-localfiles_title");
}

void TrackerDocumentProvider::deleteFile(const QUrl &file)
{
    if (QFile::exists(file.toLocalFile())) {
        QFile::remove(file.toLocalFile());

        const int count = d->model->rowCount(QModelIndex());
        for (int i = 0; i < count; ++i) {
            if (d->model->data(d->model->index(i, 0), DocumentListModel::FilePathRole).toUrl() == file) {
                d->model->removeAt(i);
                break;
            }
        }
    }
}

bool TrackerDocumentProvider::isPdf(const QString &url) const
{
    QFile file(QUrl(url).toLocalFile());
    bool pdf = file.exists();
    if (pdf) {
        pdf = file.open(QFile::ReadOnly);
        if (pdf) {
            pdf = file.read(5) == "%PDF-";
            file.close();
        }
    }
    return pdf;
}

void TrackerDocumentProvider::trackerGraphChanged(const QString &graphName)
{
    if (graphName == documentGraph) {
        startSearch();
    }
}
