/****************************************************************************
** Shared Class code from reading file 'KDbResult.shared.h'
**
** Created
**      by: The Shared Data Compiler version 0.3
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

/* This file is part of the KDE project
   Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2003-2015 Jarosław Staniek <staniek@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#ifndef KDB_RESULT_H
#define KDB_RESULT_H

#include "KDbEscapedString.h"
#include "KDbError.h"

#include <QCoreApplication>
#include <QSharedData>

class KDbMessageHandler;
class KDbMessageTitleSetter;

/*! Stores detailed information about result of recent operation.
*/
/*! @note objects of this class are implicitly shared, what means they have value semantics
          by offering copy-on-write behaviour to maximize resource usage and minimize copying.
          Only a pointer to the data is passed around. See <a href="http://doc.qt.io/qt-5/qshareddatapointer.html#details">Qt documentation</a>.
 */
//! @note This class has been generated using the following SDC class options: operator==, virtual_dtor, implicit
class KDB_EXPORT KDbResult
{
    Q_DECLARE_TR_FUNCTIONS(KDbResult)
public:





    //! @internal data class used to implement implicitly shared class KDbResult.
    //! Provides thread-safe reference counting.
    class Data : public QSharedData
    {
    public:
        Data()
        : code(ERR_NONE)
        , serverErrorCode(0)
        , serverErrorCodeSet(false)
        {
        }

        Data(const Data &other)
         : QSharedData(other)
         , code(other.code)
         , serverErrorCode(other.serverErrorCode)
         , message(other.message)
         , messageTitle(other.messageTitle)
         , errorSql(other.errorSql)
         , sql(other.sql)
         , serverMessage(other.serverMessage)
         , serverErrorCodeSet(other.serverErrorCodeSet)
        {
        }

        virtual ~Data() {}

        //! Clones the object with all attributes; the copy isn't shared with the original.
        virtual Data* clone() const { return new Data(*this); }

        bool operator==(const Data &other) const {
            return code == other.code
                   && serverErrorCode == other.serverErrorCode
                   && message == other.message
                   && messageTitle == other.messageTitle
                   && errorSql == other.errorSql
                   && sql == other.sql
                   && serverMessage == other.serverMessage
                   && serverErrorCodeSet == other.serverErrorCodeSet;
        }

        int code; //!< @see KDbResult::code(), KDbResult::setCode()
        int serverErrorCode; //!< @see KDbResult::serverErrorCode()
        QString message; //!< @see KDbResult::message(), KDbResult::setMessage()
        QString messageTitle; //!< @see KDbResult::messageTitle(), KDbResult::setMessageTitle()
        KDbEscapedString errorSql; //!< @see KDbResult::errorSql(), KDbResult::setErrorSql()
        KDbEscapedString sql; //!< @see KDbResult::sql(), KDbResult::setSql()
        QString serverMessage; //!< @see KDbResult::serverMessage(), KDbResult::setServerMessage()
        bool serverErrorCodeSet; //!< @internal
    };

    KDbResult()
     : d(new Data)
    {
    }

    KDbResult(const KDbResult &other)
     : d(other.d)
    {
    }

    virtual ~KDbResult();

    /*!
    @return result code, default is ERR_NONE (0).
    */
    int code() const {
        return d->code;
    }

    /*!
    Sets the result code if there was error.
    */
    void setCode(int code = ERR_OTHER) {
        d->code = code;
    }

    /*!
    @return an implementation-specific last server-side operation result number.
    Use this to give users more precise information about the result.

    For example, use this for your driver - default implementation just returns 0.
    Note that this value is not the same as the one returned by code().
    @sa serverMessage()
    */
    int serverErrorCode() const {
        return d->serverErrorCode;
    }

    /*!
    @return (localized) message if there was error.
    */
    QString message() const {
        return d->message;
    }

    /*!
    Sets (localized) message to @a message.
    */
    void setMessage(const QString & message) {
        d->message = message;
    }

    /*!
    @return message title that sometimes is provided and prepended
    to the main warning/error message. Used by KDbMessageHandler.
    */
    QString messageTitle() const {
        return d->messageTitle;
    }

    void setMessageTitle(const QString & messageTitle) {
        d->messageTitle = messageTitle;
    }

    KDbEscapedString errorSql() const {
        return d->errorSql;
    }

    void setErrorSql(const KDbEscapedString & errorSql) {
        d->errorSql = errorSql;
    }

    KDbEscapedString sql() const {
        return d->sql;
    }

    void setSql(const KDbEscapedString & sql) {
        d->sql = sql;
    }

    /*!
    @return message from server.
    KDb framework offers detailed result numbers using resultCode() and detailed
    result i18n-ed messages using message(). These both are (almost) not engine-dependent.
    Use setServerMessage() to users more information on the result of operation that is
    non-i18n-ed and engine-specific, usually coming from the server server side.
    */
    QString serverMessage() const {
        return d->serverMessage;
    }

    /*!
    Sets message from the server.
    */
    void setServerMessage(const QString & serverMessage) {
        d->serverMessage = serverMessage;
    }

    //! @return true if this object is equal to @a other; otherwise returns false.
    bool operator==(const KDbResult &other) const {
        return *d == *other.d;
    }

    //! @return true if this object is not equal to @a other; otherwise returns false.
    bool operator!=(const KDbResult &other) const {
        return !operator==(other);
    }


    KDbResult(int code, const QString& message);

    explicit KDbResult(const QString& message);

    //! @return true if there is an error i.e. a nonempty message, error code other
    //!         than ERR_NONE or server result has been set.
    bool isError() const;

    //! Sets an implementation-specific error code of server-side operation.
    //! Use this to give users more precise information. Implies isError() == true.
    //! The only way to clear already set server result code is to create a new KDbResult object.
    void setServerErrorCode(int errorCode);

    //! Sets result code and prepends message to an existing message.
    void prependMessage(int code, const QString& message);

    //! Prepends message to an existing message.
    void prependMessage(const QString& message);

    //! Efficient clearing of the sql attribute, equivalent of setSql(QString()).
    inline void clearSql() {
        d->sql.clear();
    }

    /*! @return sql string of actually executed SQL statement,
     usually using drv_executeSQL(). If there was error during executing SQL statement,
     before, that string is returned instead. */
    virtual inline KDbEscapedString recentSQLString() const {
        return d->errorSql;
    }

protected:
    void init(int code, const QString& message);
#if 0
    /*! Interactively asks a question. Console or GUI can be used for this,
     depending on installed message handler. For GUI version, message boxes are used.
     See KDbMessageHandler::askQuestion() for details. */
    virtual KDbMessageHandler::ButtonCode askQuestion(
            KDbMessageHandler::QuestionType messageType,
            const QString& message,
            const QString &caption = QString(),
            KDbMessageHandler::ButtonCode defaultResult = KDbMessageHandler::Yes,
            const KDbGuiItem &buttonYes = KDbGuiItem(),
            const KDbGuiItem &buttonNo = KDbGuiItem(),
            const QString &dontShowAskAgainName = QString(),
            KDbMessageHandler::Options options = 0,
            KDbMessageHandler* msgHandler = 0);

    /*! Clears number of last server operation's result stored
     as a single integer. Formally, this integer should be set to value
     that means "NO ERRORS" or "OK". This method is called by clearError().
     For reimplementation. By default does nothing.
     @sa serverMessage()
    */
    virtual void drv_clearServerResultCode() {}
#endif

protected:
    QSharedDataPointer<Data> d;
};

//! Interface for classes providing a result.
class KDB_EXPORT KDbResultable
{
public:
    KDbResultable();

    KDbResultable(const KDbResultable &other);

    KDbResultable& operator=(const KDbResultable &other);

    virtual ~KDbResultable();

    KDbResult result() const;

    void clearResult();

    /*! @return engine-specific last server-side operation result name, a name for KDbResult::serverErrorCode().
    Use this in your application to give users more information on what's up.

    Use this for your driver - default implementation just returns empty string.
    Note that this result name is not the same as the error message returned by KDbResult::serverMessage() or KDbResult::message().
    @sa KDbResult::serverMessage() */
    virtual QString serverResultName() const;

    //! Sets message handler to @a handler.
    void setMessageHandler(KDbMessageHandler *handler);

    //! @return associated message handler. 0 by default.
    KDbMessageHandler* messageHandler() const;

    void showMessage();

protected:
    friend class KDbMessageTitleSetter;
    KDbResult m_result;
    class Private;
    Private * const d;
};

//! Sends result @a result to debug output @a dbg.
KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbResult& result);

#endif // KDB_RESULT_H
