#include "piqt.h"

#include "qvariantedit.h"
#ifdef PIQT_HAS_GEOPOSITION
#  include "pigeoposition.h"

#  include <QGeoCoordinate>
#endif


QAD::Enum PI2QADEnum(const PIVariantTypes::Enum & el) {
	QAD::Enum ret;
	for (const auto & e: el.enum_list)
		ret << QAD::Enumerator(e.value, PI2QString(e.name));
	ret.selectValue(el.selectedValue());
	return ret;
}


PIVariantTypes::Enum QAD2PIEnum(const QAD::Enum & el) {
	PIVariantTypes::Enum ret;
	for (const auto & e: el.enum_list)
		ret << PIVariantTypes::Enumerator(e.value, Q2PIString(e.name));
	ret.selectValue(el.selectedValue());
	return ret;
}


QVariant PI2QVariant(const PIVariant & v) {
	switch (v.type()) {
	case PIVariant::pivBool: return QVariant(v.toBool());
	case PIVariant::pivChar:
	case PIVariant::pivUChar:
	case PIVariant::pivShort:
	case PIVariant::pivUShort:
	case PIVariant::pivInt: return QVariant(v.toInt());
	case PIVariant::pivUInt: return QVariant(uint(v.toInt()));
	case PIVariant::pivLLong: return QVariant(v.toLLong());
	case PIVariant::pivULLong: return QVariant(ullong(v.toLLong()));
	case PIVariant::pivFloat: return QVariant(v.toFloat());
	case PIVariant::pivDouble: return QVariant(v.toDouble());
	case PIVariant::pivLDouble: return QVariant(v.toDouble());
	case PIVariant::pivByteArray: return QVariant(PI2QByteArray(v.toByteArray()));
	case PIVariant::pivString: return QVariant(PI2QString(v.toString()));
	case PIVariant::pivStringList: return QVariant(PI2QStringList(v.toStringList()));
	case PIVariant::pivTime: return QVariant(PI2QTime(v.toTime()));
	case PIVariant::pivDate: return QVariant(PI2QDate(v.toDate()));
	case PIVariant::pivDateTime: return QVariant(PI2QDateTime(v.toDateTime()));
	case PIVariant::pivEnum: return QVariant::fromValue(PI2QADEnum(v.toEnum()));
	case PIVariant::pivFile: return QVariant::fromValue(PI2QADFile(v.toFile()));
	case PIVariant::pivDir: return QVariant::fromValue(PI2QADDir(v.toDir()));
	case PIVariant::pivColor: return QVariant::fromValue(PI2QColor(v.toColor()));
	case PIVariant::pivPoint: return QVariant(PI2QPoint(v.toPoint()));
	case PIVariant::pivRect: return QVariant(PI2QRect(v.toRect()));
	case PIVariant::pivLine: return QVariant(PI2QLine(v.toLine()));
	case PIVariant::pivIODevice: return QVariant::fromValue(PI2QADIODevice(v.toIODevice()));
	case PIVariant::pivMathVector: return QVariant::fromValue(PI2QMathVector(v.toMathVector()));
	case PIVariant::pivMathMatrix: return QVariant::fromValue(PI2QMathMatrix(v.toMathMatrix()));
	// case PIVariant::pivSystemTime: return QVariant(v.to());
	default: return QVariant();
	}
	return QVariant();
}


PIVariant Q2PIVariant(const QVariant & v) {
#if QT_VERSION_MAJOR <= 5
	switch (v.type()) {
#else
	switch (v.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
	case QVariant::Bool:
#else
	case QMetaType::Bool:
#endif
		return PIVariant(v.toBool());
#if QT_VERSION_MAJOR <= 5
	case QVariant::Int:
#else
	case QMetaType::Int:
#endif
		return PIVariant(v.toInt());
#if QT_VERSION_MAJOR <= 5
	case QVariant::UInt:
#else
	case QMetaType::UInt:
#endif
		return PIVariant(v.toUInt());
#if QT_VERSION_MAJOR <= 5
	case QVariant::LongLong:
#else
	case QMetaType::LongLong:
#endif
		return PIVariant(v.toLongLong());
#if QT_VERSION_MAJOR <= 5
	case QVariant::ULongLong:
#else
	case QMetaType::ULongLong:
#endif
		return PIVariant(v.toULongLong());
#if QT_VERSION_MAJOR <= 5
	case QVariant::Double:
#else
	case QMetaType::Double:
#endif
		return PIVariant(v.toDouble());
#if QT_VERSION_MAJOR <= 5
	case QVariant::ByteArray:
#else
	case QMetaType::QByteArray:
#endif
		return PIVariant(Q2PIByteArray(v.toByteArray()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::String:
#else
	case QMetaType::QString:
#endif
		return PIVariant(Q2PIString(v.toString()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::StringList:
#else
	case QMetaType::QStringList:
#endif
		return PIVariant(Q2PIStringList(v.toStringList()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::Time:
#else
	case QMetaType::QTime:
#endif
		return PIVariant(Q2PITime(v.toTime()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::Date:
#else
	case QMetaType::QDate:
#endif
		return PIVariant(Q2PIDate(v.toDate()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::DateTime:
#else
	case QMetaType::QDateTime:
#endif
		return PIVariant(Q2PIDateTime(v.toDateTime()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::Color:
#else
	case QMetaType::QColor:
#endif
		return PIVariant(Q2PIColor(v.value<QColor>()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::Point:
	case QVariant::PointF:
#else
	case QMetaType::QPoint:
	case QMetaType::QPointF:
#endif
		return PIVariant(Q2PIPoint(v.toPointF()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::Rect:
	case QVariant::RectF:
#else
	case QMetaType::QRect:
	case QMetaType::QRectF:
#endif
		return PIVariant(Q2PIRect(v.toRectF()));
#if QT_VERSION_MAJOR <= 5
	case QVariant::Line:
	case QVariant::LineF:
#else
	case QMetaType::QLine:
	case QMetaType::QLineF:
#endif
		return PIVariant(Q2PILine(v.toLineF()));
	default: break;
	}
	if (v.canConvert<float>()) return PIVariant(v.value<float>());
	if (v.canConvert<QAD::Enum>()) return PIVariant(QAD2PIEnum(v.value<QAD::Enum>()));
	if (v.canConvert<QAD::File>()) return PIVariant(QAD2PIFile(v.value<QAD::File>()));
	if (v.canConvert<QAD::Dir>()) return PIVariant(QAD2PIDir(v.value<QAD::Dir>()));
	if (v.canConvert<QAD::IODevice>()) return PIVariant(QAD2PIIODevice(v.value<QAD::IODevice>()));
	if (v.canConvert<QAD::MathVector>()) return PIVariant(Q2PIMathVector(v.value<QAD::MathVector>()));
	if (v.canConvert<QAD::MathMatrix>()) return PIVariant(Q2PIMathMatrix(v.value<QAD::MathMatrix>()));
	return PIVariant();
}


PIVariantTypes::IODevice QAD2PIIODevice(const QAD::IODevice & v) {
	PIVariantTypes::IODevice d;
	d.set(Q2PIPropertyStorage(v.props));
	d.prefix  = Q2PIString(v.prefix);
	d.mode    = v.mode;
	d.options = v.options;
	return d;
}


QAD::IODevice PI2QADIODevice(const PIVariantTypes::IODevice & v) {
	return QAD::IODevice(PI2QString(v.prefix), PI2QPropertyStorage(v.get()), v.mode, v.options);
}


QAD::File PI2QADFile(const PIVariantTypes::File & v) {
	return QAD::File(PI2QString(v.file), PI2QString(v.filter), v.is_abs, v.is_save);
}


QAD::Dir PI2QADDir(const PIVariantTypes::Dir & v) {
	return QAD::Dir(PI2QString(v.dir), v.is_abs);
}


PIVariantTypes::File QAD2PIFile(const QAD::File & v) {
	return PIVariantTypes::File(Q2PIString(v.file), Q2PIString(v.filter), v.is_abs, v.is_save);
}


PIVariantTypes::Dir QAD2PIDir(const QAD::Dir & v) {
	return PIVariantTypes::Dir(Q2PIString(v.dir), v.is_abs);
}


#ifdef PIQT_HAS_GEOPOSITION
QGeoCoordinate PI2QGeoPosition(const PIGeoPosition & v) {
	PIGeoPosition p(v);
	p.transformTo(PIGeoPosition::Cartesian);
	p.setEllipsoidModel(PIEllipsoidModel::WGS84Ellipsoid());
	p.transformTo(PIGeoPosition::Geodetic);
	return QGeoCoordinate(p.latitudeGeodetic(), p.longitude(), p.height());
}


PIGeoPosition Q2PIGeoPosition(const QGeoCoordinate & v) {
	return PIGeoPosition(PIMathVectorT3d({v.latitude(), v.longitude(), v.altitude()}), PIGeoPosition::Geodetic);
}
#endif
