/*
 * barrier -- mouse and keyboard sharing utility
 * Copyright (C) 2012-2016 Symless Ltd.
 * Copyright (C) 2004 Chris Schoeneman
 *
 * This package is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * found in the file LICENSE that should have accompanied this file.
 *
 * This package 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/>.
 */

#pragma once

#include "common/basic_types.h"
#include "common/stdmap.h"

#include <cstddef>

class EventData {
public:
    EventData() { }
    virtual ~EventData() { }
};

//! Event
/*!
A \c Event holds an event type and a pointer to event data.
*/
class Event {
public:
    typedef UInt32 Type;
    enum {
        kUnknown,    //!< The event type is unknown
        kQuit,        //!< The quit event
        kSystem,    //!< The data points to a system event type
        kTimer,        //!< The data points to timer info
        kLast        //!< Must be last
    };

    typedef UInt32 Flags;
    enum {
        kNone                = 0x00,    //!< No flags
        kDeliverImmediately    = 0x01,    //!< Dispatch and free event immediately
        kDontFreeData        = 0x02    //!< Don't free data in deleteData
    };

    Event();

    //! Create \c Event with data (POD)
    /*!
    The \p data must be POD (plain old data) allocated by malloc(),
    which means it cannot have a constructor, destructor or be
    composed of any types that do. For non-POD (normal C++ objects
    use \c setDataObject().
    \p target is the intended recipient of the event.
    \p flags is any combination of \c Flags.
    */
    Event(Type type, void* target = NULL, void* data = NULL,
                             Flags flags = kNone);

    //! @name manipulators
    //@{

    //! Release event data
    /*!
    Deletes event data for the given event (using free()).
    */
    static void            deleteData(const Event&);

    //! Set data (non-POD)
    /*!
    Set non-POD (non plain old data), where delete is called when the event
    is deleted, and the destructor is called.
    */
    void                setDataObject(EventData* dataObject);

    //@}
    //! @name accessors
    //@{

    //! Get event type
    /*!
    Returns the event type.
    */
    Type                getType() const;

    //! Get the event target
    /*!
    Returns the event target.
    */
    void*                getTarget() const;

    //! Get the event data (POD).
    /*!
    Returns the event data (POD).
    */
    void*                getData() const;

    //! Get the event data (non-POD)
    /*!
    Returns the event data (non-POD). The difference between this and
    \c getData() is that when delete is called on this data, so non-POD
    (non plain old data) dtor is called.
    */
    EventData*            getDataObject() const;

    //! Get event flags
    /*!
    Returns the event flags.
    */
    Flags                getFlags() const;

    //@}

private:
    Type                m_type;
    void*                m_target;
    void*                m_data;
    Flags                m_flags;
    EventData*            m_dataObject;
};
