/****************************************************************************
**
** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the Qt Script Debug project on Trolltech Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "qscriptdebuggerevent.h"

#include <QtCore/qdatastream.h>

/*!
  \class QScriptDebuggerEvent

  \brief The QScriptDebuggerEvent class is used to describe script debugger events.

  Debugger events are generated by QScriptDebuggerBackend
  objects. These events are typically forwarded to a
  QScriptDebuggerFrontend object, that in turn forwards the event to
  the QScriptDebuggerClient associated with the front-end.

  The type() function returns the event type. The attribute() function
  is used to query an event attribute, and the setAttribute() function
  is used to set an event attribute.

  \sa QScriptDebuggerClient
*/

/*!
  \enum QScriptDebuggerEvent::Type

  This enum specifies the possible event types.

  \value None No event.
  \value Break Evaluation break request honored.
  \value SteppingFinished Step into/over/out finished.
  \value LocationReached Location reached.
  \value Breakpoint Breakpoint hit.
  \value Exception Exception occurred.
  \value Trace Trace output received.
  \value UserEvent
  \value MaxUserEvent
*/

/*!
  \enum QScriptDebuggerEvent::Attribute

  This enum specifies the possible attributes an event can have. Which
  attributes are actually used depends on the type of event.

  \value FileName File name.
  \value LineNumber Line number.
  \value ScriptID Script ID.
  \value BreakpointID Breakpoint ID.
  \value ReturnValue Return value.
  \value ExceptionValue Exception value.
  \value HasExceptionHandler Whether an exception handler is present.
  \value Text Text.
  \value UserAttribute
  \value MaxUserAttribute
*/

class QScriptDebuggerEventPrivate
{
public:
    QScriptDebuggerEventPrivate();
    ~QScriptDebuggerEventPrivate();

    QScriptDebuggerEvent::Type type;
    QMap<QScriptDebuggerEvent::Attribute, QVariant> attributes;
};

QScriptDebuggerEventPrivate::QScriptDebuggerEventPrivate()
{
}

QScriptDebuggerEventPrivate::~QScriptDebuggerEventPrivate()
{
}

/*!
  Constructs a QScriptDebuggerEvent object of type None.
*/
QScriptDebuggerEvent::QScriptDebuggerEvent()
    : d_ptr(new QScriptDebuggerEventPrivate)
{
    d_ptr->type = None;
}

/*!
  Constructs a QScriptDebuggerEvent object of the given \a type.
*/
QScriptDebuggerEvent::QScriptDebuggerEvent(Type type)
    : d_ptr(new QScriptDebuggerEventPrivate)
{
    d_ptr->type = type;
}

/*!
  Constructs a QScriptDebuggerEvent object that is a copy of
  the \a other event.
*/
QScriptDebuggerEvent::QScriptDebuggerEvent(const QScriptDebuggerEvent &other)
    : d_ptr(new QScriptDebuggerEventPrivate)
{
    d_ptr->type = other.d_ptr->type;
    d_ptr->attributes = other.d_ptr->attributes;
}

/*!
  Assigns the \a other event to this QScriptDebuggerEvent.
*/
QScriptDebuggerEvent &QScriptDebuggerEvent::operator=(const QScriptDebuggerEvent &other)
{
    d_ptr->type = other.d_ptr->type;
    d_ptr->attributes = other.d_ptr->attributes;
    return *this;
}

/*!
  Destroys this QScriptDebuggerEvent.
*/
QScriptDebuggerEvent::~QScriptDebuggerEvent()
{
    delete d_ptr;
    d_ptr = 0;
}

/*!
  Returns the type of this event.
*/
QScriptDebuggerEvent::Type QScriptDebuggerEvent::type() const
{
    Q_D(const QScriptDebuggerEvent);
    return d->type;
}

/*!
  Returns the value of the given \a attribute, or \a defaultValue
  if the attribute is not defined.
*/
QVariant QScriptDebuggerEvent::attribute(Attribute attribute,
                                         const QVariant &defaultValue) const
{
    Q_D(const QScriptDebuggerEvent);
    return d->attributes.value(attribute, defaultValue);
}

/*!
  Sets the \a value of the given \a attribute.
*/
void QScriptDebuggerEvent::setAttribute(Attribute attribute,
                                        const QVariant &value)
{
    Q_D(QScriptDebuggerEvent);
    d->attributes[attribute] = value;
}

/*!
  Returns the line number associated with this event, or -1
  if no line number is available.
*/
int QScriptDebuggerEvent::lineNumber() const
{
    Q_D(const QScriptDebuggerEvent);
    return d->attributes.value(LineNumber, -1).toInt();
}

/*!
  Returns the ID of the script associated with this event, or -1 if no
  script ID is available.
*/
qint64 QScriptDebuggerEvent::scriptId() const
{
    Q_D(const QScriptDebuggerEvent);
    return d->attributes.value(ScriptID, -1).toLongLong();
}

/*!
  Returns the filename associated with this event, or an empty string
  if no filename is available.
*/
QString QScriptDebuggerEvent::fileName() const
{
    Q_D(const QScriptDebuggerEvent);
    return d->attributes.value(FileName, QString()).toString();
}

/*!
  \fn QDataStream &operator<<(QDataStream &stream, const QScriptDebuggerEvent &event)
  \relates QScriptDebuggerEvent

  Writes the given \a event to the specified \a stream.
*/
QDataStream &operator<<(QDataStream &out, const QScriptDebuggerEvent &event)
{
    const QScriptDebuggerEventPrivate *d = event.d_ptr;
    out << (quint32)d->type;
    out << (qint32)d->attributes.size();
    QMap<QScriptDebuggerEvent::Attribute, QVariant>::const_iterator it;
    for (it = d->attributes.constBegin(); it != d->attributes.constEnd(); ++it) {
        out << (quint32)it.key();
        out << it.value();
    }
    return out;
}

/*!
  \fn QDataStream &operator>>(QDataStream &stream, QScriptDebuggerEvent &event)
  \relates QScriptDebuggerEvent

  Reads a QScriptDebuggerEvent from the specified \a stream into the
  given \a event.
*/
QDataStream &operator>>(QDataStream &in, QScriptDebuggerEvent &event)
{
    QScriptDebuggerEventPrivate *d = event.d_ptr;

    quint32 type;
    in >> type;
    d->type = QScriptDebuggerEvent::Type(type);

    qint32 attribCount;
    in >> attribCount;
    QMap<QScriptDebuggerEvent::Attribute, QVariant> attribs;
    for (qint32 i = 0; i < attribCount; ++i) {
        quint32 key;
        in >> key;
        QVariant value;
        in >> value;
        attribs[QScriptDebuggerEvent::Attribute(key)] = value;
    }
    d->attributes = attribs;

    return in;
}
