/********************************************************************
Copyright 2015  Martin Gräßlin <mgraesslin@kde.org>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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 6 of version 3 of the license.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef WAYLAND_TOUCH_H
#define WAYLAND_TOUCH_H

#include <QObject>
#include <QPoint>

#include <KWayland/Client/kwaylandclient_export.h>

struct wl_touch;

namespace KWayland
{
namespace Client
{

class Surface;
class Touch;

/**
 * TODO
 */
class KWAYLANDCLIENT_EXPORT TouchPoint
{
public:
    virtual ~TouchPoint();

    /**
     * Unique in the scope of all TouchPoints currently being down.
     * As soon as the TouchPoint is now longer down another TouchPoint
     * might get assigned the id.
     **/
    qint32 id() const;
    /**
     * The serial when the down event happened.
     **/
    quint32 downSerial() const;
    /**
     * The serial when the up event happened.
     **/
    quint32 upSerial() const;
    /**
     * Most recent timestamp
     **/
    quint32 time() const;
    /**
     * All timestamps, references the positions.
     * That is each position has a timestamp.
     **/
    QVector<quint32> timestamps() const;
    /**
     * Most recent position
     **/
    QPointF position() const;
    /**
     * All positions this TouchPoint had, updated with each move.
     **/
    QVector<QPointF> positions() const;
    /**
     * The Surface this TouchPoint happened on.
     **/
    QPointer<Surface> surface() const;
    /**
     * @c true if currently down, @c false otherwise.
     **/
    bool isDown() const;

private:
    friend class Touch;
    explicit TouchPoint();
    class Private;
    QScopedPointer<Private> d;
};

/**
 * @short Wrapper for the wl_touch interface.
 *
 * This class is a convenient wrapper for the wl_touch interface.
 *
 * To create an instance use Seat::createTouch.
 *
 * @see Seat
 **/
class KWAYLANDCLIENT_EXPORT Touch : public QObject
{
    Q_OBJECT
public:
    explicit Touch(QObject *parent = nullptr);
    virtual ~Touch();

    /**
     * @returns @c true if managing a wl_pointer.
     **/
    bool isValid() const;
    /**
     * Setup this Touch to manage the @p touch.
     * When using Seat::createTouch there is no need to call this
     * method.
     **/
    void setup(wl_touch *touch);
    /**
     * Releases the wl_touch interface.
     * After the interface has been released the Touch instance is no
     * longer valid and can be setup with another wl_touch interface.
     *
     * This method is automatically invoked when the Seat which created this
     * Touch gets released.
     **/
    void release();
    /**
     * Destroys the data held by this Touch.
     * This method is supposed to be used when the connection to the Wayland
     * server goes away. If the connection is not valid anymore, it's not
     * possible to call release anymore as that calls into the Wayland
     * connection and the call would fail. This method cleans up the data, so
     * that the instance can be deleted or set up to a new wl_touch interface
     * once there is a new connection available.
     *
     * This method is automatically invoked when the Seat which created this
     * Touch gets destroyed.
     *
     * @see release
     **/
    void destroy();

    /**
     * The TouchPoints of the latest touch event sequence.
     * Only valid till the next touch event sequence is started
     **/
    QVector<TouchPoint*> sequence() const;

    operator wl_touch*();
    operator wl_touch*() const;

Q_SIGNALS:
    /**
     * A new touch sequence is started. The previous sequence is discarded.
     * @param startPoint The first point which started the sequence
     **/
    void sequenceStarted(KWayland::Client::TouchPoint *startPoint);
    /**
     * Sent if the compositor decides the touch stream is a global
     * gesture.
     **/
    void sequenceCanceled();
    /**
     * Emitted once all touch points are no longer down.
     **/
    void sequenceEnded();
    /**
     * Indicates the end of a contact point list.
     **/
    void frameEnded();
    /**
     * TouchPoint @p point got added to the sequence.
     **/
    void pointAdded(KWayland::Client::TouchPoint *point);
    /**
     * TouchPoint @p point is no longer down.
     * A new TouchPoint might reuse the Id of the @p point.
     **/
    void pointRemoved(KWayland::Client::TouchPoint *point);
    /**
     * TouchPoint @p point moved.
     **/
    void pointMoved(KWayland::Client::TouchPoint *point);

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

}
}

Q_DECLARE_METATYPE(KWayland::Client::TouchPoint*)

#endif
