#include "inputviewfactory.h"
#include "inputviewfactory_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QMetaType>

#include <QtQml/qqml.h>

#include <QtMvvmCore/private/qtmvvm_logging_p.h>

#include "formatters_p.h"

using namespace QtMvvm;

InputViewFactory::InputViewFactory(QObject *parent) :
	QObject(parent),
	d(new InputViewFactoryPrivate())
{}

InputViewFactory::~InputViewFactory() = default;

QUrl InputViewFactory::getInputUrl(const QByteArray &type, const QVariantMap &viewProperties)
{
	QUrl url;

	Q_UNUSED(viewProperties)
	if(d->inputAliases.contains(type))
		url = getInputUrl(d->inputAliases.value(type), viewProperties);
	else if(d->simpleInputs.contains(type))
		url = d->simpleInputs.value(type);
	else {
		logCritical() << "Failed to find any input view for input type:" << type;
		return QUrl();
	}

	logDebug() << "Found view URL for input of type" << type << "as" << url;
	return url;
}

QUrl InputViewFactory::getDelegate(const QByteArray &type, const QVariantMap &viewProperties)
{
	QUrl url;

	Q_UNUSED(viewProperties)
	if(d->delegateAliases.contains(type))
		url = getDelegate(d->delegateAliases.value(type), viewProperties);
	else if(d->simpleDelegates.contains(type))
		url = d->simpleDelegates.value(type);
	else if((type == "selection" || type == "list") &&
			!viewProperties.value(QStringLiteral("editable"), false).toBool())
		url = QStringLiteral("qrc:/qtmvvm/delegates/ListDelegate.qml");
	else
		url = QStringLiteral("qrc:/qtmvvm/delegates/MsgDelegate.qml");

	logDebug() << "Found view URL for delegate of type" << type << "as" << url;
	return url;
}

QString QtMvvm::InputViewFactory::format(const QByteArray &type, const QString &formatString, const QVariant &value, const QVariantMap &viewProperties)
{
	if(d->formatterAliases.contains(type))
		return format(d->formatterAliases.value(type), formatString, value, viewProperties);
	else if(d->formatters.contains(type))
		return d->formatters.value(type)->format(formatString, value, viewProperties);
	else
		return formatString.arg(value.toString());
}

void InputViewFactory::addSimpleInput(const QByteArray &type, const QUrl &qmlFileUrl)
{
	d->simpleInputs.insert(type, qmlFileUrl);
}

void InputViewFactory::addSimpleDelegate(const QByteArray &type, const QUrl &qmlFileUrl)
{
	d->simpleDelegates.insert(type, qmlFileUrl);
}

void InputViewFactory::addFormatter(const QByteArray &type, Formatter *formatter)
{
	d->formatters.insert(type, QSharedPointer<Formatter>{formatter});
}

void InputViewFactory::addInputAlias(const QByteArray &alias, const QByteArray &targetType)
{
	d->inputAliases.insert(alias, targetType);
}

void InputViewFactory::addDelegateAlias(const QByteArray &alias, const QByteArray &targetType)
{
	d->delegateAliases.insert(alias, targetType);
}

void QtMvvm::InputViewFactory::addFormatterAlias(const QByteArray &alias, const QByteArray &targetType)
{
	d->formatterAliases.insert(alias, targetType);
}



Formatter::Formatter() = default;

Formatter::~Formatter() = default;



InputViewFactoryPrivate::InputViewFactoryPrivate() :
	simpleInputs{
		{QMetaType::typeName(QMetaType::Bool), QStringLiteral("qrc:/qtmvvm/inputs/CheckBox.qml")},
		{"switch", QStringLiteral("qrc:/qtmvvm/inputs/Switch.qml")},
		{QMetaType::typeName(QMetaType::QString), QStringLiteral("qrc:/qtmvvm/inputs/TextField.qml")},
		{"string", QStringLiteral("qrc:/qtmvvm/inputs/TextField.qml")},
		{QMetaType::typeName(QMetaType::Int), QStringLiteral("qrc:/qtmvvm/inputs/SpinBox.qml")},
		{QMetaType::typeName(QMetaType::Double), QStringLiteral("qrc:/qtmvvm/inputs/DoubleSpinBox.qml")},
//		{QMetaType::typeName(QMetaType::QDate), QStringLiteral("qrc:/qtmvvm/inputs/.qml")},
//		{QMetaType::typeName(QMetaType::QTime), QStringLiteral("qrc:/qtmvvm/inputs/.qml")},
//		{QMetaType::typeName(QMetaType::QDateTime), QStringLiteral("qrc:/qtmvvm/inputs/.qml")},
//		{"date", QStringLiteral("qrc:/qtmvvm/inputs/.qml")},
		{QMetaType::typeName(QMetaType::QFont), QStringLiteral("qrc:/qtmvvm/inputs/FontEdit.qml")},
		{QMetaType::typeName(QMetaType::QUrl), QStringLiteral("qrc:/qtmvvm/inputs/UrlField.qml")},
		{"selection", QStringLiteral("qrc:/qtmvvm/inputs/ListEdit.qml")},
		{"list", QStringLiteral("qrc:/qtmvvm/inputs/ListEdit.qml")},
		{"radiolist", QStringLiteral("qrc:/qtmvvm/inputs/RadioListEdit.qml")}
	},
	simpleDelegates{
		{QMetaType::typeName(QMetaType::Bool), QStringLiteral("qrc:/qtmvvm/delegates/BoolDelegate.qml")},
		{"switch", QStringLiteral("qrc:/qtmvvm/inputs/SwitchDelegate.qml")}
	},
	formatters{
		{QMetaType::typeName(QMetaType::Int), QSharedPointer<IntFormatter>::create()},
		{QMetaType::typeName(QMetaType::Double), QSharedPointer<SimpleFormatter<double>>::create()},
	}
{
	auto listFormatter = QSharedPointer<ListFormatter>::create();
	formatters.insert("selection", listFormatter);
	formatters.insert("list", listFormatter);
	formatters.insert("radiolist", listFormatter);
}