/* This file is part of the Chakra project

   Copyright (C) 2010 Lukas Appelhans <l.appelhans@gmx.de>

   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 AKABEIDATABASEHANDLER_H
#define AKABEIDATABASEHANDLER_H

#include "akabeiclient_global.h"

#include <akabeierror.h>

#include <QObject>
#include <QUrl>
#include <QNetworkReply>

namespace Akabei {
    class Database;
}

namespace AkabeiClient {
/**
 * \class DatabaseHandler  akabeidatabasehandler.h "akabeidatabasehandler.h"
 *
 * \brief A wrapper around Akabei::Database with network support.
 * 
 * This class is thread-safe.
 */
class AKABEICLIENTSHARED_EXPORT DatabaseHandler : public QObject
{
    Q_OBJECT
    public:
        /**
         * Describes the status of the database handler
         */
        enum Status
        {
            StatusBare = 0, ///Default status
            StatusDownloading = 1, ///Currently downloading
            StatusUpdating = 2, ///Currently updating the database
            StatusFinished = 3, ///Updating finished
            StatusError = 4, ///An error occurred
            StatusUpToDate = 5 ///Database already up-to-date
        };
        /**
         * Describes an error which occurred during updating
         */
        enum Error
        {
            OpenFileFailure = QNetworkReply::ProtocolFailure + 1,///Cannot open file on disk
            ExtractArchiveFailure = OpenFileFailure + 1///Cannot extract archive
        };
        virtual ~DatabaseHandler();

        /**
         * @returns the name of the database, unlike Akabei::Database::name() this something like "core"
         */
        QString name() const;
        /**
         * @returns the status the database is currently in
         */
        Status status() const;

        /**
         * @brief It is possible for a DatabaseHandler instance to point to a non-valid object
         * at some point of its lifetime, for example if it is a new database that is yet to
         * be downloaded and processed.
         *
         * @returns Returns whether this handler points to a valid database object.
         */
        bool isValid() const;
        /**
         * Updates the database
         * @param force force update even if databases are up-to-date already
         */
        void update(bool force = false);

        /**
         * @returns the database the DatabaseHandler is handling
         */
        Akabei::Database * database();
        /**
         * @returns the mirror of the database
         */
        QUrl mirror() const;
        /**
         * Sets the mirror of the database
         * @param url the new mirror
         */
        void setMirror(const QUrl &url);

    Q_SIGNALS:
        /**
         * The progress while updating changed
         * @param percent the progress in percent
         */
        void progress(int percent);
        /**
         * The status of the DatabaseHandler changed
         * @param status the new status of the DatabaseHandler
         */
        void statusChanged(AkabeiClient::DatabaseHandler::Status status);
        /**
         * An error got caught
         * @param error the integer is either a QNetworkReply::Error or a DatabaseHandler::Error
         */
        void errorTriggered(Akabei::Error::List);

    private:
        DatabaseHandler(Akabei::Database *db, const QString &name, const QUrl &mirror, QObject * parent);
        DatabaseHandler(const QString &name, const QUrl &mirror, QObject * parent);

        void setDatabase(Akabei::Database * db);

        friend class Configuration;
        friend class ConfigurationPrivate;
        class Private;
        Private *d;

        Q_PRIVATE_SLOT(d, void __k__finishedDownload(bool))
        Q_PRIVATE_SLOT(d, void __k__finished(bool))
};
}

Q_DECLARE_METATYPE(AkabeiClient::DatabaseHandler::Status)

#endif
