/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/

/* Code inspired by KOffice libwmf and adapted for Scribus by Jean Ghali */

#ifndef WMFIMPORT_H
#define WMFIMPORT_H

#include <QColor>
#include <QList>
#include <QSize>
#include <QtXml/QtXml>

#include "pluginapi.h"
#include "fpointarray.h"
#include "wmfcontext.h"

class QBuffer;
class QTextCodec;

class FPointArray;
class PageItem;
class ScribusDoc;
class Selection;
class PrefsManager;
class TransactionSettings;

class  WmfCmd;
class  WmfObjHandle;
class  WmfObjPenHandle;
class  WmfObjBrushHandle;
struct WmfPlaceableHeader;

class WMFImport : public QObject
{
	Q_OBJECT

public:
	WMFImport(ScribusDoc* doc, int flags);
	~WMFImport() override;

	bool importFile(const QString& fname, const TransactionSettings& trSettings, int flags);
	QImage readThumbnail(const QString& fn);

	bool interactive { false };
	//! \brief Indicator if there is any unsupported feature in imported wmf.
    bool unsupported { false };
	bool importFailed { false };
    bool importCanceled { true };

protected:
	QString m_docDesc;
	QString m_docTitle;

	ScribusDoc* m_Doc { nullptr };
	Selection* m_tmpSel { nullptr };
	QStringList importedColors;

	WMFContext m_context;

    bool m_IsPlaceable { false };
    bool m_IsEnhanced { false };
    bool m_Valid { false };

    // coordinate system
    QRect  m_HeaderBoundingBox;
    QRect  m_BBox;

	QList<WmfCmd*> m_commands;
    WmfObjHandle** m_ObjHandleTab { nullptr };
    FPointArray    m_Points;
    int            m_Dpi { 1440 };

	/** Protected import functions */
	bool importWMF(const TransactionSettings& trSettings, int flags);
	bool loadWMF(const QString& fileName);
	bool loadWMF(QBuffer& buffer);

	QList<PageItem*> parseWmfCommands(void);

	void finishCmdParsing(PageItem* item);

	/** Import a QColor */
	QString importColor(const QColor& color);

	/** Get color from parameters array */
	QColor  colorFromParam(const short* params );

	/** Get text codec from charset code */
	QTextCodec* codecFromCharset(int charset);

	/** Translate characters in symbol charset to unicode */
	QString symbolToUnicode(const QByteArray& chars) const;

	/** Get polygon array from parameters array */
	FPointArray pointsFromParam(short num, const short* params) const;

	/** Transform a point array to an item path used as polyline */
	FPointArray pointsToPolyline(const FPointArray& points, bool closePath) const;

	void pointsToAngle(double xStart, double yStart, double xEnd, double yEnd, double& angleStart, double& angleLength) const;

	/** Handle win-object-handles */
	void addHandle(WmfObjHandle*);
	void deleteHandle(int);

	/** Calculate header checksum */
	unsigned short calcCheckSum(WmfPlaceableHeader*);

	/** Find function in metafunc table by metafile-function.
		Returns index or -1 if not found. */
	virtual int findFunc(unsigned short aFunc) const;

	/** Converts two parameters to long */
	unsigned int toDWord(const short* params);

public:

	/** set window origin */
	void setWindowOrg(QList<PageItem*>& items, long num, const short* params);
	/** set window extents */
	void setWindowExt(QList<PageItem*>& items, long num, const short* params);

	/****************** Drawing *******************/
	/** draw line to coord */
	void lineTo(QList<PageItem*>& items, long num, const short* params);
	/** move pen to coord */
	void moveTo(QList<PageItem*>& items, long num, const short* params);
	/** draw ellipse */
	void ellipse(QList<PageItem*>& items, long num, const short* params);
	/** draw polygon */
	void polygon(QList<PageItem*>& items, long num, const short* params);
	/** draw a list of polygons */
	void polyPolygon(QList<PageItem*>& items, long num, const short* params);
	/** draw series of lines */
	void polyline(QList<PageItem*>& items, long num, const short* params);
	/** draw a rectangle */
	void rectangle(QList<PageItem*>& items, long num, const short* params);
	/** draw round rectangle */
	void roundRect(QList<PageItem*>& items, long num, const short* params);
	/** draw arc */
	void arc(QList<PageItem*>& items, long num, const short* params);
	/** draw chord */
	void chord(QList<PageItem*>& items, long num, const short* params);
	/** draw pie */
	void pie(QList<PageItem*>& items, long num, const short* params);
	/** set polygon fill mode */
	void setPolyFillMode(QList<PageItem*>& items, long num, const short* params);
	/** set background pen color */
	void setBkColor(QList<PageItem*>& items, long num, const short* params);
	/** set background pen mode */
	void setBkMode(QList<PageItem*>& items, long num, const short* params);
	/** save device context */
	void saveDC(QList<PageItem*>& items, long num, const short* params);
	/** restore device context */
	void restoreDC(QList<PageItem*>& items, long num, const short* params);
	/**  clipping region is the intersection of this region and the original region */
	void intersectClipRect(QList<PageItem*>& items, long num, const short* params);
	/** delete a clipping rectangle of the original region */
	void excludeClipRect(QList<PageItem*>& items, long num, const short* params);

	/****************** Text *******************/
	/** set text color */
	void setTextColor(QList<PageItem*>& items, long num, const short* params);
	/** set text alignment */
	void setTextAlign(QList<PageItem*>& items, long num, const short* params);
	/** draw text */
	void textOut(QList<PageItem*>& items, long num, const short* params);
	void extTextOut(QList<PageItem*>& items, long num, const short* params);

	/****************** Object handle *******************/
	/** Activate object handle */
	void selectObject(QList<PageItem*>& items, long num, const short* params);
	/** Free object handle */
	void deleteObject(QList<PageItem*>& items, long num, const short* params);
	/** create an empty object in the object list */
	void createEmptyObject(QList<PageItem*>& items, long num, const short* params);
	/** create a logical brush */
	void createBrushIndirect(QList<PageItem*>& items, long num, const short* params);
	/** create a logical pen */
	void createPenIndirect(QList<PageItem*>& items, long num, const short* params);
	/** create a logical font */
	void createFontIndirect(QList<PageItem*>& items, long num, const short* params);

	/****************** misc *******************/
	/** nothing to do */
	void noop(QList<PageItem*>& items, long, const short*);
	/** end of meta file */
	void end(QList<PageItem*>& items, long /*num*/, const short* /*params*/);
};

#endif
