/* This file is part of the Chakra project

   Copyright (C) 2012 Lukas Appelhans <boom1992@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 POLKITARCHIVEHANDLER_H
#define POLKITARCHIVEHANDLER_H

#include <libarchive++/archivehandler.h>
#include <QDBusMessage>

/**
 * @class PolKitArchiveHandler
 * @brief Wraps archivehandler around polkit and executes operations in helper app if necessary.
 *
 * This class is not thread-safe.
 */
class AKABEICORESHARED_EXPORT PolKitArchiveHandler : public QObject
{
Q_OBJECT
public:
    /**
     * Creates a new PolKitArchiveHandler object from an archive, reading all the entries contained.
     * @param path the archive pathname.
     * @throw ArchiveException if something goes wrong while reading the archive.
     */
    PolKitArchiveHandler(const QString &, QObject * parent = nullptr);
    virtual ~PolKitArchiveHandler();

    QString filename() const;

    /**
     * Writes a new archive to disk
     * @param filename the path of the archive
     * @param files a \c QHash of files. The first value is the path inside the archive on disk, the second one the file on disk.
     * @returns true if successful
     */
    static bool write(const QString& filename, const QHash<QString, QString>& files);

    /**
     * @returns a list of the filenames contained in the archive.
     */
    QStringList getEntries() const;

    /**
     * @param fileName the file name.
     * @returns the size of an archive file.
     * @throw ArchiveException if the file doesn't exist.
     */
    size_t getEntrySize(QString const& fileName) const;

    /**
     * @returns the total size of all archive files.
     */
    size_t totalEntrySize() const;

    /**
     * Reads a text file.
     * @param textFile the archive file to read.
     * @returns a string with the text contained.
     * @throw ArchiveException if the files doesn't exist.
     */
    QString readTextFile(const QString&);

    /**
     * Extracts a single entry.
     * @param source the filename.
     * @param destName the name it will have once extracted.
     * @param overwrite overwrite if already existent.
     * @throw ArchiveException if the file isn't in the archive or the extraction goes wrong.
     * @Note if the file requested is a directory, this function extracts all its subtree too.
     * @Note if overwrite is false and the file already exists, nothing happens.
     */
    void extract(const QString& source, const QString& destName, bool overwrite);
    void extract(const ArchiveEntry &entry, const QString& destName, bool overwrite);

    /**
     * Extracts all entries.
     * @param prefix the prefix path they will assume.
     * @param overwrite overwrite if already present.
     */
    void extractAll(const QString&, bool overwrite);

    /**
     * Computes the MD5 hash of some archive entries.
     * @param files the files to be computed.
     * @returns a \c QByteArray list with their hash in the same order as the input.
     * @throw ArchiveException if at least one of the files doesn't exist or is a directory.
     */
    QList<QByteArray> md5(const QStringList&);

    /**
     * @see md5
     * Convenience method for when there's just one file to compute
     */
    QByteArray md5(const QString &);

    /**
     * @returns whether a package archive contains a PKGINFO.
     */
    bool checkPackageValidity();

    /**
     * @returns a list of errors occurred during execution
     */
    Akabei::Error::List errors();

private:
    /* Disable default and copy constructors */
    PolKitArchiveHandler(PolKitArchiveHandler const&);

    class Private;
    Private *d;
};

Q_DECLARE_METATYPE(QList<QByteArray>)

#endif
