#ifndef PIQT_H
#define PIQT_H

#include "pimathmatrix.h"
#include "pipropertystorage.h"
#include "qad_types.h"
#include <QVector3D>
#include <QDateTime>
#include <QColor>
#if QT_VERSION >= 0x050200
#  include "pigeoposition.h"
#endif


class QGeoCoordinate;


const QVariant PI2QVariant(const PIVariant & v);
const PIVariant Q2PIVariant(const QVariant & v);

//inline const QString PI2QString(const PIString & v) {return QString::fromLocal8Bit(v.data());}
inline const QString PI2QString(const PIString & v) {return QString::fromUtf8(v.dataUTF8());}

//inline const PIString Q2PIString(const QString & v) {return PIString(v.toLocal8Bit().data());}
inline const PIString Q2PIString(const QString & v) {return PIString::fromUTF8(v.toUtf8().data());}


inline const QStringList PI2QStringList(const PIStringList & v) {QStringList ret; piForeachC (PIString & s, v) ret << PI2QString(s); return ret;}

inline const PIStringList Q2PIStringList(const QStringList & v) {PIStringList ret; foreach (const QString & s, v) ret << Q2PIString(s); return ret;}


inline const QByteArray PI2QByteArray(const PIByteArray & v) {return QByteArray((const char *)(v.data()), v.size_s());}

inline const PIByteArray Q2PIByteArray(const QByteArray & v) {return PIByteArray(v.constData(), v.size());}


inline const QPointF PI2QVector2(const PIMathVectorT2d & v) {return QPointF(v[0], v[1]);}
inline const QVector3D PI2QVector3(const PIMathVectorT3d & v) {return QVector3D(v[0], v[1], v[2]);}

inline const PIMathVectorT2d Q2PIVector2(const QPointF & v) {return createVectorT2d(double(v.x()), double(v.y()));}
inline const PIMathVectorT3d Q2PIVector3(const QVector3D & v) {return createVectorT3d(double(v.x()), double(v.y()), double(v.z()));}

inline const QPointF PI2QPoint(const PIPointd & v) {return QPointF(v.x, v.y);}
inline const PIPointd Q2PIPoint(const QPointF & v) {return PIPointd(v.x(), v.y());}

inline const QRectF PI2QRect(const PIRectd & v) {return QRectF(v.x0, v.y0, v.width(), v.height());}
inline const PIRectd Q2PIRect(const QRectF & v) {return PIRectd(v.x(), v.y(), v.width(), v.height());}

inline const QAD::MathVector PI2QMathVector(const PIMathVectord & v) {
	QVector<double> q = QVector<double>(v.size());
	memcpy(q.data(), v.data(), q.size()*sizeof(double));
	return QAD::MathVector(q);
}
inline const PIMathVectord Q2PIMathVector(const QAD::MathVector & v) {
	PIMathVectord p = PIMathVectord(v.v.size());
	memcpy(p.data(), v.v.data(), p.size()*sizeof(double));
	return p;
}

inline const QAD::MathMatrix PI2QMathMatrix(const PIMathMatrixd & v) {
	PIVector<PIVector<double> > p = v.toVectors();
	QVector<QVector<double> > q = QVector<QVector<double> >(p.size());
	for (int i = 0; i < q.size(); ++i) {
		q[i].resize(p[i].size());
		memcpy(q[i].data(), p[i].data(), q[i].size()*sizeof(double));
	}
	return QAD::MathMatrix(q);
}
inline const PIMathMatrixd Q2PIMathMatrix(const QAD::MathMatrix & v) {
	PIVector<PIVector<double> > p = PIVector<PIVector<double> >(v.m.size());
	for (int i = 0; i < v.m.size(); ++i) {
		p[i].resize(v.m[i].size());
		memcpy(p[i].data(), v.m[i].data(), p[i].size()*sizeof(double));
	}
	return PIMathMatrixd(p);
}


inline const QDate PI2QDate(const PIDate & v) {return QDate(v.year, v.month, v.day);}
inline const QTime PI2QTime(const PITime & v) {return QTime(v.hours, v.minutes, v.seconds, v.milliseconds);}
inline const QDateTime PI2QDateTime(const PIDateTime & v) {return QDateTime(PI2QDate(v.date()), PI2QTime(v.time()));}

inline const PIDate Q2PIDate(const QDate & v) {return PIDate(v.year(), v.month(), v.day());}
inline const PITime Q2PITime(const QTime & v) {return PITime(v.hour(), v.minute(), v.second(), v.msec());}
inline const PIDateTime Q2PIDateTime(const QDateTime & v) {return PIDateTime(Q2PIDate(v.date()), Q2PITime(v.time()));}


inline const QColor PI2QColor(const PIVariantTypes::Color & v) {return QColor::fromRgba(v.rgba);}
inline const PIVariantTypes::Color Q2PIColor(const QColor & v) {return PIVariantTypes::Color(v.rgba());}


inline PIPropertyStorage Q2PIPropertyStorage(const PropertyStorage & props) {
	PIPropertyStorage ret;
	foreach (const PropertyStorage::Property & p, props)
		ret.addProperty(Q2PIString(p.name), Q2PIVariant(p.value), Q2PIString(p.comment), p.flags);
	return ret;
}

inline PropertyStorage PI2QPropertyStorage(const PIPropertyStorage & props) {
	PropertyStorage ret;
	piForeachC (PIPropertyStorage::Property & p, props)
		ret.addProperty(PI2QString(p.name), PI2QVariant(p.value), PI2QString(p.comment), p.flags);
	return ret;
}


const QAD::Enum PI2QADEnum(const PIVariantTypes::Enum & el);
const QAD::File PI2QADFile(const PIVariantTypes::File & v);
const QAD::Dir PI2QADDir(const PIVariantTypes::Dir & v);
const QAD::IODevice PI2QADIODevice(const PIVariantTypes::IODevice & v);
const PIVariantTypes::Enum QAD2PIEnum(const QAD::Enum & el);
const PIVariantTypes::File QAD2PIFile(const QAD::File & v);
const PIVariantTypes::Dir QAD2PIDir(const QAD::Dir & v);
const PIVariantTypes::IODevice QAD2PIIODevice(const QAD::IODevice & v);

//inline const PIVariant QString2PIVariant(const QString & v) {return PIVariant::readFromString(QString2PIString(v));}

#if QT_VERSION >= 0x050200
const QGeoCoordinate PI2QGeoPosition(const PIGeoPosition & v);
const PIGeoPosition Q2PIGeoPosition(const QGeoCoordinate & v);
#endif

template <typename From>
class __PIQtConverter {
public:
	__PIQtConverter(const From & v): val(v) {}
	template <typename To> operator To() {return To();}
	From val;
};
template<typename From> inline __PIQtConverter<From> __PIQtConvert(const From & f) {return __PIQtConverter<From>(f);}

#define _PIQt_CONVERT(ft, tt, ftc, tfc) \
template<> template<> inline __PIQtConverter<ft>::operator tt() {return ftc(val);} \
template<> template<> inline __PIQtConverter<tt>::operator ft() {return tfc(val);}
#define _PIQt_CONVERT_S(t) _PIQt_CONVERT(PI##t, Q##t, PI2Q##t, Q2PI##t)

_PIQt_CONVERT_S(String)
_PIQt_CONVERT_S(ByteArray)
_PIQt_CONVERT_S(Time)
_PIQt_CONVERT_S(Date)
_PIQt_CONVERT_S(DateTime)
_PIQt_CONVERT(PIMathVectorT2d, QPointF, PI2QVector2, Q2PIVector2)
_PIQt_CONVERT(PIMathVectorT3d, QVector3D, PI2QVector3, Q2PIVector3)

#define piqt __PIQtConvert
#define qtpi __PIQtConvert

#endif // PIQT_H
