/*
 * <one line to give the library's name and an idea of what it does.>
 * Copyright 2013  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) 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 14 of version 3 of the license.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef ABSTRACTSQLITECONNECTION_H
#define ABSTRACTSQLITECONNECTION_H

#include <sqlite3.h>

#include <QString>
#include <QVariantMap>

#include <exception>
#include <QSharedDataPointer>


    typedef QVariantMap Row;

/**
 * @class SQLiteResource
 * @brief Used by SQLiteConnection to store the result of a query
 */
class SQLiteResource
{
    typedef QVariant Value;
public:
    SQLiteResource(QList<Row>);
    SQLiteResource(const SQLiteResource &other);
    ~SQLiteResource();

    /**
     * @param rowNumber the row number in the result table
     * @param columnName the column name
     * @returns the value of the specified cell
     */
    QVariant getDataAt(int, QString const&) const;

    /**
     * @param columnName the column name
     * @returns a list of values of that column
     */
    QList<QVariant> getColumn(QString const&) const;

    /**
     * @returns the number of rows in this table
     */
    int getRowsCount() const;

    SQLiteResource &operator=(const SQLiteResource &other);

private:
    class Private;
    QSharedDataPointer<Private> d;
};

class AbstractSQLiteConnection
{
public:
    virtual ~AbstractSQLiteConnection();
    
    /**
     * Establishes a new connection with a database
     *
     * @param name the database filename
     * @param readonly true if read-only access, false for read-write
     */
    virtual void connectToDB(QString const&, bool) = 0;

    /**
     * Executes a query on the database
     *
     * @param q the query string
     * @returns a SQLiteResource object with the result, if present
     */
    virtual SQLiteResource query(const QString &q) = 0;

    /**
     * Executes multiple queries on the database
     *
     * @param q the query
     * @param bindings the bindings we're going to use
     *                 this is pair of values, the key is a string determining the binding name, the value is a stringlist which contains all the values
     */
    virtual void query(const QString &q, const QVariantMap &bindings) = 0;

    /**
     * If the table interested by the last query as an autoincremented primary key,
     * gets the last value assigned to the key
     */
    virtual qint64 getLastRowId() = 0;

    /**
     * Creates a "macro" (fake name) that maps into an integer, a QString, or a QByteArray
     * The next query can contain the defined macros in place of the actual values.
     * @note All bindings stay valid only for the subsequent call of query().
     */
    virtual void bind(QString const&, int) = 0;
    virtual void bind(QString const&, QString const&) = 0;
    virtual void bind(QString const&, QByteArray const&) = 0;
};


class SQLiteException : public std::exception
{
public:
    SQLiteException(const char *m) : message(m) {}

    virtual const char *what() const throw() override {
        return message;
    }

private:
    const char *message;
};

Q_DECLARE_METATYPE(QList<Row>)

#endif // ABSTRACTSQLITECONNECTION_H
