#include "virtual_keyboard_layout_page.h"

#include <QApplication>
#include <QBoxLayout>
#include <QJsonArray>
#include <QJsonObject>
#include <QKeyEvent>
#include <QTimer>

static const char property_role[]    = "role";
static const char property_page[]    = "page";
static const char property_stretch[] = "stretch";


VirtualKeyboardLayoutPage::VirtualKeyboardLayoutPage(QJsonObject root) {
	auto main_lay = new QBoxLayout(QBoxLayout::TopToBottom);
	name_         = root["name"].toString();
	auto rows     = root["rows"].toArray();
	for (auto row: rows) {
		auto rowa            = row.toArray();
		QBoxLayout * row_lay = nullptr;
		int cur_cols         = 0;
		for (auto rb: rowa) {
			auto * b = createButton(rb.toObject());
			if (!b) continue;
			if (!row_lay) row_lay = new QBoxLayout(QBoxLayout::LeftToRight);
			buttons << b;
			row_lay->addWidget(b, b->property(property_stretch).toInt());
			++cur_cols;
		}
		if (row_lay) main_lay->addLayout(row_lay);
		columns = piMaxi(columns, cur_cols);
	}
	// qDebug() << "VirtualKeyboardLayoutPage" << name;
	setLayout(main_lay);
}


VirtualKeyboardLayoutPage::~VirtualKeyboardLayoutPage() {}


void VirtualKeyboardLayoutPage::setCapital(bool yes) {
	capital = yes;
	for (auto b: buttons) {
		auto role = buttonRole(b);
		if (role == rLetter) {
			b->setText(yes ? b->text().toUpper() : b->text().toLower());
		}
		if (role == rShift) {
			// b->setText(yes ? QString::fromUtf8("⇫") : QString::fromUtf8("⇧"));
			b->setChecked(yes);
		}
	}
}


void VirtualKeyboardLayoutPage::setGotoEnabled(bool yes) {
	for (auto b: buttons) {
		auto role = buttonRole(b);
		if (role == rGotoPage) b->setEnabled(yes);
	}
}


void VirtualKeyboardLayoutPage::setCapitalEnabled(bool yes) {
	capital_enabled = yes;
	for (auto b: buttons) {
		auto role = buttonRole(b);
		if (role == rShift) b->setEnabled(yes);
	}
}


void VirtualKeyboardLayoutPage::setButtonsSize(int h) {
	for (auto b: buttons) {
		b->setFixedHeight(h);
	}
	if (!isVisible()) {
		adjustSize();
		layout()->invalidate();
	}
}


QToolButton * VirtualKeyboardLayoutPage::createButton(QJsonObject jb) {
	QString role_str = jb["role"].toString();
	if (role_str.isEmpty()) return nullptr;
	auto ret    = new QToolButton();
	int role    = roleFromText(role_str);
	int stretch = jb["stretch"].toInt();
	if (stretch == 0) stretch = 1;
	auto text = jb["text"].toString();
	ret->setProperty(property_role, role);
	ret->setProperty(property_stretch, stretch);
	ret->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
	ret->setFocusPolicy(Qt::NoFocus);
	ret->setMinimumSize(QSize(2, 2));
	ret->setAutoRepeat(true);
	switch (role) {
	case rBackspace: text = QString::fromUtf8("⌫"); break;
	case rReturn: text = QString::fromUtf8("⏎"); break;
	case rSpace: text = QString::fromUtf8("────"); break;
	case rShift:
		text = QString::fromUtf8("⤊");
		ret->setCheckable(true);
		break; // ⇪⇧⇫⇯⇩⬆⌨
	case rHide: text = QString::fromUtf8("⨂"); break;
	case rGotoPage: ret->setProperty(property_page, jb["page"].toString()); break;
	}
	ret->setText(text);
	connect(ret, &QToolButton::clicked, this, [this, role, ret](bool press) {
		int key = 0;
		QString text;
		switch (role) {
		case rLetter:
			text = ret->text();
			if (text.startsWith('&')) text.remove(0, 1);
			break;
		case rBackspace: key = Qt::Key_Backspace; break;
		case rReturn: key = Qt::Key_Return; break;
		case rSpace:
			key  = Qt::Key_Space;
			text = " ";
			break;
		case rHide: emit hideRequest(); break;
		case rShift: setCapital(!isCapital()); break;
		case rGotoPage: emit gotoPageRequest(ret->property(property_page).toString()); break;
		}
		if (key == 0 && text.isEmpty()) return;
		QApplication::postEvent(QApplication::focusWidget(), new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, text));
		QApplication::postEvent(QApplication::focusWidget(), new QKeyEvent(QEvent::KeyRelease, key, Qt::NoModifier, text));
		if (role == rLetter && isCapital() && capital_enabled) setCapital(false);
	});
	return ret;
}


VirtualKeyboardLayoutPage::Role VirtualKeyboardLayoutPage::roleFromText(QString str) {
	str = str.toLower();
	if (str == "l") return rLetter;
	if (str == "backspace") return rBackspace;
	if (str == "return") return rReturn;
	if (str == "space") return rSpace;
	if (str == "hide") return rHide;
	if (str == "shift") return rShift;
	if (str == "gotopage") return rGotoPage;
	return rInvalid;
}


VirtualKeyboardLayoutPage::Role VirtualKeyboardLayoutPage::buttonRole(QToolButton * b) const {
	if (!b) return rInvalid;
	return static_cast<Role>(b->property(property_role).toInt());
}
