#ifndef PQPAINTER_H
#define PQPAINTER_H

#include <QPainter>
#include <pqobject.h>
#include "pqpixmap.h"
#include "pqpen.h"
#include "pqbrush.h"

class PQPainter;
class PQPainter : public PQObject, public QPainter
{
    Q_OBJECT
    PQ_OBJECT_EX(QPainter)

public:
    Q_INVOKABLE explicit PQPainter();
    ~PQPainter();

    Q_INVOKABLE bool begin(PQObject *pqpixmap);

    Q_INVOKABLE bool end();
    Q_INVOKABLE bool isActive() const;

    Q_INVOKABLE bool initFrom(PQObject *pqobject);

    Q_INVOKABLE void setCompositionMode(int mode);
    Q_INVOKABLE int compositionMode() const;

   // const QFont &font() const;
   // void setFont(const QFont &f);

   // QFontMetrics fontMetrics() const;
   // QFontInfo fontInfo() const;

    Q_INVOKABLE void setPen(const QString &color);
    Q_INVOKABLE void setPen(PQObject *pen);
    Q_INVOKABLE void setPen(int style);
    Q_INVOKABLE PQPen *pen();

   // void setBrush(const QBrush &brush);
   // void setBrush(Qt::BrushStyle style);
   // const QBrush &brush() const;

    // attributes/modes
    Q_INVOKABLE void setBackgroundMode(int mode);
    Q_INVOKABLE int backgroundMode() const;

    Q_INVOKABLE QPoint brushOrigin() const;
    Q_INVOKABLE void setBrushOrigin(double x, double y);
    Q_INVOKABLE void setBrushOrigin(int x, int y);

    Q_INVOKABLE void setBackground(PQObject *bg);
    Q_INVOKABLE PQBrush *background() const;

    Q_INVOKABLE double opacity() const;
    Q_INVOKABLE void setOpacity(double opacity);

    // Clip functions
    //QRegion clipRegion() const;
    //QPainterPath clipPath() const;

    //void setClipRect(const QRectF &, Qt::ClipOperation op = Qt::ReplaceClip);
    //void setClipRect(const QRect &, Qt::ClipOperation op = Qt::ReplaceClip);
    //void setClipRect(int x, int y, int w, int h, Qt::ClipOperation op = Qt::ReplaceClip);

    //void setClipRegion(const QRegion &, Qt::ClipOperation op = Qt::ReplaceClip);

    //void setClipPath(const QPainterPath &path, Qt::ClipOperation op = Qt::ReplaceClip);

    //void setClipping(bool enable);
   // bool hasClipping() const;

    //QRectF clipBoundingRect() const;

    Q_INVOKABLE void save();
    Q_INVOKABLE void restore();

    // XForm functions
    /*
    void setMatrix(const QMatrix &matrix, bool combine = false);
    const QMatrix &matrix() const;
    const QMatrix &deviceMatrix() const;
    void resetMatrix();

    void setTransform(const QTransform &transform, bool combine = false);
    const QTransform &transform() const;
    const QTransform &deviceTransform() const;
    void resetTransform();

    void setWorldMatrix(const QMatrix &matrix, bool combine = false);
    const QMatrix &worldMatrix() const;

    void setWorldTransform(const QTransform &matrix, bool combine = false);
    const QTransform &worldTransform() const;

    QMatrix combinedMatrix() const;
    QTransform combinedTransform() const;

    void setMatrixEnabled(bool enabled);
    bool matrixEnabled() const;

    void setWorldMatrixEnabled(bool enabled);
    bool worldMatrixEnabled() const;
*/
    Q_INVOKABLE void scale(double sx, double sy);
    Q_INVOKABLE void shear(double sh, double sv);
    Q_INVOKABLE void rotate(double a);

    //void translate(const QPointF &offset);
   // inline void translate(const QPoint &offset);
    Q_INVOKABLE void translate(double dx, double dy);
    Q_INVOKABLE void translate(int dx, int dy);

    Q_INVOKABLE QRect window() const;
    Q_INVOKABLE void setWindow(int x, int y, int w, int h);

    Q_INVOKABLE QRect viewport() const;
    Q_INVOKABLE void setViewport(int x, int y, int w, int h);

    Q_INVOKABLE void setViewTransformEnabled(bool enable);
    Q_INVOKABLE bool viewTransformEnabled() const;

    // drawing functions
    //void strokePath(const QPainterPath &path, const QPen &pen);
    //void fillPath(const QPainterPath &path, const QBrush &brush);
    //void drawPath(const QPainterPath &path);

    Q_INVOKABLE void drawPoint(int x, int y);
    Q_INVOKABLE void drawPoint(double x, double y);

    Q_INVOKABLE void drawLine(int x1, int y1, int x2, int y2);
    Q_INVOKABLE void drawLine(double x1, double y1, double x2, double y2);

    Q_INVOKABLE void drawRect(int x1, int y1, int w, int h);
    Q_INVOKABLE void drawRect(double x1, double y1, double w, double h);

    Q_INVOKABLE void drawEllipse(int x, int y, int w, int h);
    Q_INVOKABLE void drawEllipse(double x1, double y1, double w, double h);

    //void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);
    //void drawPolygon(const QPolygonF &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);
    //void drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);
    //void drawPolygon(const QPolygon &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);

    //void drawConvexPolygon(const QPointF *points, int pointCount);
    //inline void drawConvexPolygon(const QPolygonF &polygon);
    //void drawConvexPolygon(const QPoint *points, int pointCount);
    //inline void drawConvexPolygon(const QPolygon &polygon);

    //void drawArc(const QRectF &rect, int a, int alen);
    //inline void drawArc(const QRect &, int a, int alen);
    Q_INVOKABLE void drawArc(int x, int y, int w, int h, int a, int alen);
    Q_INVOKABLE void drawArc(double x, double y, double w, double h, double a, double alen);

    //void drawPie(const QRectF &rect, int a, int alen);
    Q_INVOKABLE void drawPie(int x, int y, int w, int h, int a, int alen);
    Q_INVOKABLE void drawPie(double x, double y, double w, double h, double a, double alen);
    //inline void drawPie(const QRect &, int a, int alen);

    //void drawChord(const QRectF &rect, int a, int alen);
    Q_INVOKABLE void drawChord(int x, int y, int w, int h, int a, int alen);
    Q_INVOKABLE void drawChord(double x, double y, double w, double h, double a, double alen);
    //inline void drawChord(const QRect &, int a, int alen);

    //void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
    //                     Qt::SizeMode mode = Qt::AbsoluteSize);
    Q_INVOKABLE void drawRoundedRect(int x, int y, int w, int h, double xRadius, double yRadius,
                                int mode = Qt::AbsoluteSize);
    Q_INVOKABLE void drawRoundedRect(double x, double y, double w, double h, double xRadius, double yRadius,
                                int mode = Qt::AbsoluteSize);
    //inline void drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
    //                            Qt::SizeMode mode = Qt::AbsoluteSize);

    //void drawRoundRect(const QRectF &r, int xround = 25, int yround = 25);
    //void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25);
    //inline void drawRoundRect(const QRect &r, int xround = 25, int yround = 25);

    //void drawTiledPixmap(const QRectF &rect, const QPixmap &pm, const QPointF &offset = QPointF());
    Q_INVOKABLE void drawTiledPixmap(int x, int y, int w, int h,
                         PQObject *pqpixmap, int sx=0, int sy=0);
    Q_INVOKABLE void drawTiledPixmap(double x, double y, double w, double h,
                         PQObject *pqpixmap, double sx=0, double sy=0);
    //inline void drawTiledPixmap(const QRect &, const QPixmap &, const QPoint & = QPoint());

    //void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect);
    //inline void drawPixmap(const QRect &targetRect, const QPixmap &pixmap, const QRect &sourceRect);
    Q_INVOKABLE void drawPixmap(int x, int y, int w, int h, PQObject *pqpixmap,
                           int sx, int sy, int sw, int sh);
    Q_INVOKABLE void drawPixmap(int x, int y, PQObject *pqpixmap,
                           int sx, int sy, int sw, int sh);
    Q_INVOKABLE void drawPixmap(int x, int y, int w, int h, PQObject *pqpixmap);
    Q_INVOKABLE void drawPixmap(int x, int y, PQObject *pqpixmap);

    Q_INVOKABLE void drawPixmap(double x, double y, double w, double h, PQObject *pqpixmap,
                           double sx, double sy, double sw, double sh);
    Q_INVOKABLE void drawPixmap(double x, double y, PQObject *pqpixmap,
                           double sx, double sy, double sw, double sh);
    Q_INVOKABLE void drawPixmap(double x, double y, PQObject *pqpixmap);

    /*
    void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
                   Qt::ImageConversionFlags flags = Qt::AutoColor);
    inline void drawImage(const QRect &targetRect, const QImage &image, const QRect &sourceRect,
                          Qt::ImageConversionFlags flags = Qt::AutoColor);
    inline void drawImage(const QPointF &p, const QImage &image, const QRectF &sr,
                          Qt::ImageConversionFlags flags = Qt::AutoColor);
    inline void drawImage(const QPoint &p, const QImage &image, const QRect &sr,
                          Qt::ImageConversionFlags flags = Qt::AutoColor);
    inline void drawImage(const QRectF &r, const QImage &image);
    inline void drawImage(const QRect &r, const QImage &image);
    void drawImage(const QPointF &p, const QImage &image);
    inline void drawImage(const QPoint &p, const QImage &image);
    inline void drawImage(int x, int y, const QImage &image, int sx = 0, int sy = 0,
                          int sw = -1, int sh = -1, Qt::ImageConversionFlags flags = Qt::AutoColor);
    */

    Q_INVOKABLE void setLayoutDirection(int direction);
    Q_INVOKABLE int layoutDirection() const;

    /*
    void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
    inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
    inline void drawStaticText(int left, int top, const QStaticText &staticText);

    void drawText(const QPointF &p, const QString &s);
    inline void drawText(const QPoint &p, const QString &s);
    inline void drawText(int x, int y, const QString &s);

    void drawText(const QPointF &p, const QString &str, int tf, int justificationPadding);

    void drawText(const QRectF &r, int flags, const QString &text, QRectF *br = Q_NULLPTR);
    void drawText(const QRect &r, int flags, const QString &text, QRect *br = Q_NULLPTR);
    inline void drawText(int x, int y, int w, int h, int flags, const QString &text, QRect *br = Q_NULLPTR);

    void drawText(const QRectF &r, const QString &text, const QTextOption &o = QTextOption());


    QRectF boundingRect(const QRectF &rect, int flags, const QString &text);
    QRect boundingRect(const QRect &rect, int flags, const QString &text);
    inline QRect boundingRect(int x, int y, int w, int h, int flags, const QString &text);

    QRectF boundingRect(const QRectF &rect, const QString &text, const QTextOption &o = QTextOption());

    void drawTextItem(const QPointF &p, const QTextItem &ti);
    inline void drawTextItem(int x, int y, const QTextItem &ti);
    inline void drawTextItem(const QPoint &p, const QTextItem &ti);
    */

    //void fillRect(const QRectF &, const QBrush &);
    //inline void fillRect(int x, int y, int w, int h, const QBrush &);
    //void fillRect(const QRect &, const QBrush &);

    //void fillRect(const QRectF &, const QColor &color);
    Q_INVOKABLE void fillRect(int x, int y, int w, int h, const QString &color);
    Q_INVOKABLE void fillRect(double x, double y, double w, double h, const QString &color);
    //void fillRect(const QRect &, const QColor &color);

    /*
    inline void fillRect(int x, int y, int w, int h, Qt::GlobalColor c);
    inline void fillRect(const QRect &r, Qt::GlobalColor c);
    inline void fillRect(const QRectF &r, Qt::GlobalColor c);

    inline void fillRect(int x, int y, int w, int h, Qt::BrushStyle style);
    inline void fillRect(const QRect &r, Qt::BrushStyle style);
    inline void fillRect(const QRectF &r, Qt::BrushStyle style);
    */

    //void eraseRect(const QRectF &);
    Q_INVOKABLE void eraseRect(int x, int y, int w, int h);
    Q_INVOKABLE void eraseRect(double x, double y, double w, double h);
    //inline void eraseRect(const QRect &);

    Q_INVOKABLE void setRenderHint(int hint, bool on = true);
    Q_INVOKABLE void setRenderHints(int hints, bool on = true);
    Q_INVOKABLE int renderHints() const;
    Q_INVOKABLE bool testRenderHint(int hint);

    //QPaintEngine *paintEngine() const;

    //static void setRedirected(const QPaintDevice *device, QPaintDevice *replacement,
    //                          const QPoint& offset = QPoint());
    //static QPaintDevice *redirected(const QPaintDevice *device, QPoint *offset = Q_NULLPTR);
    //static void restoreRedirected(const QPaintDevice *device);

    Q_INVOKABLE void beginNativePainting();
    Q_INVOKABLE void endNativePainting();
};

Q_DECLARE_METATYPE(QPainter*)
Q_DECLARE_METATYPE(PQPainter*)

#endif // PQPAINTER_H
