/* This file is part of the Chakra project

   Copyright (C) 2010 Dario Freddi <drf@chakra-project.org>

   This program 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 2 of the License, or (at your option) any later version.
*/

#ifndef AKABEI_HELPERS_H
#define AKABEI_HELPERS_H


#include <QEventLoop>
#include <QUuid>
#include <QHash>

#include "AbstractSQLiteConnection.h"
#include <akabeicore_global.h>

struct sqlite3;

namespace Akabei {
class Package;
class Database;
class Group;
class Hook;
class Delta;

namespace Helpers
{
enum Permission {
    NoPermission = 0x00,
    ReadPermission = 0x01,
    WritePermission = 0x02,
    ReadWritePermission = 0x03
};
Q_DECLARE_FLAGS(Permissions, Permission)
QByteArray md5sum(const QByteArray &data);
QByteArray md5sumOfFile(const QString &path);
QByteArray processMd5(unsigned char output[]);

QHash< QString, QString > versionedTargets(const QStringList &targets);
QPair< QString, QString > versionedTarget(const QString& target);

QStringList unversionedTargets(const QStringList &targets);
QString unversionedTarget(const QString &target);

Package *latestVersionOfPackage(QString const& pkgName);

bool removeFile(const QString &file);
bool copyFile(const QString &source, const QString &destination);

Permissions permissionsOfPath(const QString &path);

bool checkAuthorizationSync(const QString &action);
        
/*
 * Converts a size in floating point to a string representation.
 * It is designed to replace the similar function in KIO, since we avoid KDE dependencies in akabei.
 * It was taken from Solid.
 */
QString formatByteSize(double size);

/*
 * Returns the amount of available partition space, given the path of a generic file/directory
 * inside the partition.
 * 
 * In case of errors, 0 is returned.
 */
qlonglong availablePartitionSpace(const QByteArray &);

namespace QueryPerformer
{
    int AKABEICORESHARED_EXPORT beginTransaction(Akabei::Database *db);
    int AKABEICORESHARED_EXPORT beginTransaction(AbstractSQLiteConnection &);
    int AKABEICORESHARED_EXPORT commitTransaction(Akabei::Database *db);
    int AKABEICORESHARED_EXPORT commitTransaction(AbstractSQLiteConnection &);
    int AKABEICORESHARED_EXPORT rollbackTransaction(Akabei::Database *db);
    int AKABEICORESHARED_EXPORT rollbackTransaction(AbstractSQLiteConnection &);

    int AKABEICORESHARED_EXPORT insertPackage(Akabei::Database *db, Package *p);
    int AKABEICORESHARED_EXPORT insertPackage(AbstractSQLiteConnection &, Package *p);

    int AKABEICORESHARED_EXPORT updatePackage(Akabei::Database *db, Package *from, Package *to);
    int AKABEICORESHARED_EXPORT updatePackage(AbstractSQLiteConnection &, Package *from, Package *to);
    int AKABEICORESHARED_EXPORT updatePackage(AbstractSQLiteConnection &, int from, Package *to);

    int AKABEICORESHARED_EXPORT removePackage(Akabei::Database *db, Package *p);
    int AKABEICORESHARED_EXPORT removePackage(AbstractSQLiteConnection &, Package *p);

    int AKABEICORESHARED_EXPORT insertGroup(Akabei::Database *db, Group *g);
    int AKABEICORESHARED_EXPORT insertGroup(AbstractSQLiteConnection &, Group *g);

    int AKABEICORESHARED_EXPORT removeGroup(Akabei::Database *db, Group *g);
    int AKABEICORESHARED_EXPORT removeGroup(AbstractSQLiteConnection &, Group *g);

    int AKABEICORESHARED_EXPORT insertDelta(Akabei::Database *db, Delta const *delta, int packageId);
    int AKABEICORESHARED_EXPORT insertDelta(AbstractSQLiteConnection &, Delta const *delta, int packageId);

    int AKABEICORESHARED_EXPORT removeDeltas(Akabei::Database *db, Package const* p);
    int AKABEICORESHARED_EXPORT removeDeltas(AbstractSQLiteConnection &, Package const* p);
    int AKABEICORESHARED_EXPORT removeDelta(Akabei::Database *db, Delta const* delta);
    int AKABEICORESHARED_EXPORT removeDelta(AbstractSQLiteConnection &, Delta const* delta);

    int AKABEICORESHARED_EXPORT insertFiles(Akabei::Database *db, Package *p);
    int AKABEICORESHARED_EXPORT insertFiles(AbstractSQLiteConnection&, Package *p);

    int AKABEICORESHARED_EXPORT updateFiles(Akabei::Database *db, Package *from, Package *to);
    int AKABEICORESHARED_EXPORT updateFiles(AbstractSQLiteConnection &, Package *from, Package *to);
    int AKABEICORESHARED_EXPORT updateFiles(AbstractSQLiteConnection &, int from, Package *to);

    int AKABEICORESHARED_EXPORT removeFiles(Akabei::Database *db, Package *p);
    int AKABEICORESHARED_EXPORT removeFiles(AbstractSQLiteConnection &, Package *p);
    int AKABEICORESHARED_EXPORT removeFiles(AbstractSQLiteConnection &, int package);

    int AKABEICORESHARED_EXPORT insertScriptlet(Akabei::Database *db, Package *p);
    int AKABEICORESHARED_EXPORT insertScriptlet(AbstractSQLiteConnection &, Package *p);

    int AKABEICORESHARED_EXPORT updateScriptlet(Akabei::Database *db, Package *from, Package *to);
    int AKABEICORESHARED_EXPORT updateScriptlet(AbstractSQLiteConnection &, Package *from, Package *to);
    int AKABEICORESHARED_EXPORT updateScriptlet(AbstractSQLiteConnection &, int from, Package *to);

    int AKABEICORESHARED_EXPORT removeScriptlet(Akabei::Database *db, Package *p);
    int AKABEICORESHARED_EXPORT removeScriptlet(AbstractSQLiteConnection &, Package *p);
    int AKABEICORESHARED_EXPORT removeScriptlet(AbstractSQLiteConnection &, int packageId);

    int AKABEICORESHARED_EXPORT insertHook(Akabei::Database *db, Hook const* hook);
    int AKABEICORESHARED_EXPORT insertHook(AbstractSQLiteConnection &, Hook const* hook);

    int AKABEICORESHARED_EXPORT removeHook(Akabei::Database *db, Hook const* hook);
    int AKABEICORESHARED_EXPORT removeHook(AbstractSQLiteConnection &, Hook const* hook);
}

class PackageEventLoop : public QEventLoop
{
    Q_OBJECT
    Q_DISABLE_COPY(PackageEventLoop)
    public:
        PackageEventLoop(QObject *parent = nullptr);
        virtual ~PackageEventLoop();

        void setUuid(const QUuid &uuid);

        QList<Akabei::Package*> result() const;

    public Q_SLOTS:
        void requestQuit(const QUuid &uuid, const QList<Akabei::Package*> &result);

    private:
        class Private;
        Private * const d;
};

}

}

#endif // AKABEI_HELPERS_P_H
