#include "piqt_connection_view.h"

#include "picodeinfo.h"
#include "piqt.h"

#include <alignedtextitem.h>


DeviceItem::DeviceItem(): BlockItem() {
	addProperty(BlockItem::Property("__type", "", __CV_Device));
	addProperty(BlockItem::Property("bufferSize", "", 4096));
	setSize(200, 80);
	setColor(QColor(192, 192, 255));
	text_name = new AlignedTextItem();
	text_path = new AlignedTextItem();
	QFont fnt(text_name->font());
	fnt.setBold(true);
	text_name->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
	text_name->setFont(fnt);
	text_name->setPos(0., -size().height() / 2.);
	addDecor(text_name);
	fnt.setBold(false);
	fnt.setPointSizeF(fnt.pointSizeF() - 2.);
	text_path->setFont(fnt);
	text_path->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
	text_path->setPos(0., -size().height() / 2. + 20);
	addDecor(text_path);
	addPin(Qt::AlignLeft, 0, "write", "");
	addPin(Qt::AlignRight, 0, "read", "");
}


void DeviceItem::rename() {
	QString ms;
	BlockItemPin *pr = pinByText("read"), *pw = pinByText("write");
	switch (mode()) {
	case PIIODevice::ReadOnly:
		ms = "ro";
		pr->show();
		pw->hide();
		break;
	case PIIODevice::WriteOnly:
		ms = "wo";
		pr->hide();
		pw->show();
		break;
	case PIIODevice::ReadWrite:
		ms = "rw";
		pr->show();
		pw->show();
		break;
	}
	text_name->setText(name() + " (" + ms + ")");
	text_path->setText(path());
}


FilterItem::FilterItem(): BlockItem() {
	addProperty(BlockItem::Property("__type", "", __CV_Filter));
	addProperty(BlockItem::Property("bufferSize", "", 65536));
	setSize(140, 80);
	setPos(200, 0);
	setColor(QColor(192, 255, 192));
	text_name = new AlignedTextItem();
	text_mode = new AlignedTextItem();
	QFont fnt(text_name->font());
	fnt.setBold(true);
	text_name->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
	text_name->setFont(fnt);
	text_name->setPos(0., -size().height() / 2.);
	addDecor(text_name);
	fnt.setBold(false);
	fnt.setPointSizeF(fnt.pointSizeF() - 2.);
	text_mode->setFont(fnt);
	text_mode->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
	text_mode->setPos(0., -size().height() / 2. + 20);
	addDecor(text_mode);
	addPin(Qt::AlignLeft, 0, "in", "");
	addPin(Qt::AlignRight, 0, "out", "");
}


void FilterItem::rename() {
	text_name->setText(name());
	QString ms;
	PICodeInfo::EnumInfo * ei = PICODEINFO::enums().value("PIPacketExtractor::SplitMode", 0);
	if (ei) {
		for (const auto & i: ei->members)
			if (i.value == mode()) {
#if PIP_VERSION >= PIP_MAKE_VERSION(2, 39, 0)
				ms = PI2QString(i.name.toString());
#else
				ms = PI2QString(i.name);
#endif
				break;
			}
	}
	text_mode->setText(ms);
}


SenderItem::SenderItem(): BlockItem() {
	addProperty(BlockItem::Property("__type", "", __CV_Sender));
	setSize(140, 80);
	setPos(-200, 0);
	setColor(QColor(255, 192, 192));
	text_name      = new AlignedTextItem();
	text_frequency = new AlignedTextItem();
	QFont fnt(text_name->font());
	fnt.setBold(true);
	text_name->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
	text_name->setFont(fnt);
	text_name->setPos(0., -size().height() / 2.);
	addDecor(text_name);
	fnt.setBold(false);
	fnt.setPointSizeF(fnt.pointSizeF() - 2.);
	text_frequency->setFont(fnt);
	text_frequency->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
	text_frequency->setPos(0., -size().height() / 2. + 20);
	addDecor(text_frequency);
	addPin(Qt::AlignRight, 0, "out", "");
}


void SenderItem::rename() {
	text_name->setText(name());
	text_frequency->setText(QString::number(frequency()) + " Hz");
}


ConnectionView::ConnectionView(QWidget * parent): BlockView(parent) {}


ConnectionView::~ConnectionView() {}


DeviceItem * ConnectionView::addDevice(const QString & name, const QString & path) {
	DeviceItem * ret = findDevice(name);
	if (ret) return ret;
	ret = new DeviceItem();
	PIString dp;
	PIIODevice::DeviceMode dm;
	PIIODevice::splitFullPath(Q2PIString(path), &dp, &dm);
	ret->setPos(0, 0);
	ret->setName(name);
	ret->setPath(PI2QString(dp));
	ret->setMode(dm);
	ret->setDisconnectTimeout(3.);
	ret->setBufferSize(4096);
	placeBlock(ret, allDevices());
	addItem(ret);
	return ret;
}


FilterItem * ConnectionView::addFilter(const QString & name) {
	FilterItem * ret = new FilterItem();
	ret->setDisconnectTimeout(3.);
	ret->setBufferSize(65536);
	ret->setName(name);
	placeBlock(ret, allFilters());
	addItem(ret);
	return ret;
}


SenderItem * ConnectionView::addSender(const QString & name) {
	SenderItem * ret = new SenderItem();
	ret->setName(name);
	placeBlock(ret, allSenders());
	addItem(ret);
	return ret;
}


DeviceItem * ConnectionView::findDevice(const QString & name) const {
	QList<BlockItem *> blockl = blocks();
	foreach(BlockItem * b, blockl)
		if ((b->propertyByName("name").value == name) && (b->propertyByName("__type").value.toInt() == __CV_Device)) return (DeviceItem *)b;
	return 0;
}


void ConnectionView::loadBus(BlockBusItem * bus) {
	bus->setEndpointsNumber(2);
}


void ConnectionView::placeBlock(BlockItem * b, QList<BlockItem *> coll) {
	if (coll.isEmpty()) return;
	QList<QRectF> collr;
	foreach(BlockItem * i, coll)
		collr << i->sceneBoundingRect();
	while (true) {
		QRectF br = b->sceneBoundingRect();
		bool ok   = true;
		for (int i = 0; i < collr.size(); ++i)
			if (br.intersects(collr[i])) {
				ok = false;
				break;
			}
		if (ok) break;
		b->moveBy(0., grid_step);
	}
	b->moveBy(0., grid_step * 2.);
}


QList<BlockItem *> ConnectionView::allByType(int type_) const {
	QList<BlockItem *> blockl = blocks(), ret;
	foreach(BlockItem * b, blockl)
		if (b->propertyByName("__type").value.toInt() == type_) ret << b;
	return ret;
}
