#include "dialogpannel.h"
#include "ui_dialogpannel.h"
#include "tb_interface.h"
#include <algorithm>
#include <QSpinBox>
#include <QLineEdit>
#include <QDoubleSpinBox>
#include <QScrollArea>
#include <QComboBox>
#include <QLabel>
#include <QGridLayout>
DialogPannel::DialogPannel(const TASKBUS::cmdlineParser * ps, QWidget *parent) :
	QDialog(parent),
	ui(new Ui::DialogPannel),
	m_log(new QStandardItemModel(this)),
	m_pCmd(ps),
	m_rthread(new reciv_thread(ps,this))
{
	ui->setupUi(this);
	ui->listView_log->setModel(m_log);
	connect(m_rthread,&reciv_thread::sig_quit,this,&DialogPannel::close);
	connect(m_rthread,&reciv_thread::new_message,this,&DialogPannel::deal_message,Qt::QueuedConnection);
	Qt::WindowFlags flg = windowFlags();
	flg |= Qt::WindowMinMaxButtonsHint;
	setWindowFlags(flg);
	m_rthread->start();	
}

DialogPannel::~DialogPannel()
{
	m_rthread->terminate();
	m_rthread->wait();
	delete ui;
}

void DialogPannel::deal_message(QString message)
{
	m_log->appendRow(new QStandardItem(message));
	if (m_log->rowCount()>256)
		m_log->removeRows(0,m_log->rowCount()-256);
	std::map<std::string, std::string> cmd = TASKBUS::string_to_map(message.toStdString());
	if (cmd["function"]==std::string("handle_annouce"))
		AddHandle(cmd);
	else if (cmd["function"]==std::string("handle_set"))
	{
		const QString handle = QString::fromStdString(cmd["handle"]).trimmed();
		const QString value = QString::fromStdString(cmd["value"]).trimmed();
		const QString source = QString::fromStdString(cmd["source"]).trimmed();
		if (!m_handles.contains(source))
			return;
		if (!m_handles[source].contains(handle))
			return;
		if (m_handles[source][handle])
			m_handles[source][handle](value);
	}
}

void DialogPannel::AddHandle(std::map<std::string, std::string> & cmd)
{
	const QString source = QString::fromStdString(cmd["source"]).trimmed();
	const QString handle = QString::fromStdString(cmd["handle"]).trimmed();
	const QString label = QString::fromStdString(cmd["label"]).trimmed();
	const QString type = QString::fromStdString(cmd["type"]).trimmed();
	const QString range = QString::fromStdString(cmd["range"]).trimmed();
	const QString value = QString::fromStdString(cmd["value"]).trimmed();
	const QString step = QString::fromStdString(cmd["step"]).trimmed();
	const QString decimal = QString::fromStdString(cmd["decimal"]).trimmed();

	if (source.length()<1 || handle.length()<1)
		return;

	if (!m_tabs.contains(source))
	{
		QScrollArea * area = new QScrollArea(this);
		QGridLayout * grid_layout = new QGridLayout(this);
		area->setLayout(grid_layout);
		ui->tabWidget->addTab(area,QString("source=%1").arg(source));
		m_tabs[source] = grid_layout;
	}
	QGridLayout * grid_layout = m_tabs[source];

	if (m_handles[source].contains(handle))
		return;

	const int nRows = grid_layout->rowCount();
	QWidget * w = 0;
	if (type=="int")
	{
		QStringList rgs = range.split(":",Qt::SkipEmptyParts);
		long long n_min = 0, n_max = 0;
		if (rgs.size()==2)
		{
			n_min = rgs.first().toLongLong();
			n_max = rgs.last().toLongLong();
		}
		//Create
		if (n_min < n_max)
		{
			QDoubleSpinBox * s = new QDoubleSpinBox(this);
			s->setRange(n_min,n_max);
			s->setValue(value.toInt());
			s->setDecimals(0);
			s->setSingleStep(step.toInt()==0?1:step.toInt());
			w = s;
			connect(s,&QDoubleSpinBox::valueChanged,[=](double newv)->void{
				QString nv = QString("%1").arg((long long)newv);
				HandleChanged(source,handle,nv);
			});
			m_handles[source][handle] = [=](QString newv)->void{
				long long nv = newv.toLongLong();
				if (nv>= s->minimum() && nv <=s->maximum())
					s->setValue(nv);
			};
		}
		else
		{
			QLineEdit * v = new QLineEdit(this);
			v->setText(value);
			w = v;
			connect(v,&QLineEdit::returnPressed,[=]()->void{
				HandleChanged(source,handle,v->text());
			});
			m_handles[source][handle] = [=](QString newv)->void{
				v->setText(newv);
			};
		}
	}
	else if (type=="double")
	{
		QStringList rgs = range.split(":",Qt::SkipEmptyParts);
		double n_min = 0, n_max = 0;
		if (rgs.size()==2)
		{
			n_min = rgs.first().toDouble();
			n_max = rgs.last().toDouble();
		}
		//Create
		if (n_min < n_max)
		{
			QDoubleSpinBox * s = new QDoubleSpinBox(this);
			s->setRange(n_min,n_max);
			s->setValue(value.toDouble());
			s->setDecimals(decimal.toInt());
			s->setSingleStep(step.toInt()==0?1:step.toInt());
			w = s;
			connect(s,&QDoubleSpinBox::valueChanged,[=](double newv)->void{
				QString nv = QString("%1").arg(newv,0,'f',2);
				HandleChanged(source,handle,nv);
			});
			m_handles[source][handle] = [=](QString newv)->void{
				double nv = newv.toInt();
				if (nv>= s->minimum() && nv <=s->maximum())
					s->setValue(nv);
			};
		}
		else
		{
			QLineEdit * v = new QLineEdit(this);
			v->setText(value);
			w = v;
			connect(v,&QLineEdit::returnPressed,[=]()->void{
				HandleChanged(source,handle,v->text());
			});
			m_handles[source][handle] = [=](QString newv)->void{
				v->setText(newv);
			};
		}
	}
	else
	{
		QStringList rgs = range.split(",",Qt::SkipEmptyParts);
		if (rgs.size())
		{
			QComboBox * c = new QComboBox(this);
			QStandardItemModel * m = new QStandardItemModel(this);
			c->setModel(m);
			foreach(QString s, rgs)
				m->appendRow(new QStandardItem(s));
			c->setCurrentText(value);
			w = c;
			connect(c,&QComboBox::currentIndexChanged,[=](int idx)->void{
				if (idx<0||idx>m->rowCount())
					HandleChanged(source,handle,"");
				else
					HandleChanged(source,handle,m->data(m->index(idx,0)).toString());
			});
			m_handles[source][handle] = [=](QString newv)->void{
				c->setCurrentText(newv);
			};
		}
		else
		{
			QLineEdit * v = new QLineEdit(this);
			v->setText(value);
			w = v;
			connect(v,&QLineEdit::returnPressed,[=]()->void{
				HandleChanged(source,handle,v->text());
			});
			m_handles[source][handle] = [=](QString newv)->void{
				v->setText(newv);
			};
		}
	}
	m_ctrls[source][handle] = w;
	QLabel * lb = new QLabel(this);
	lb->setText(handle);
	if (label.length())
		lb->setText(label);
	grid_layout->addWidget(lb,nRows,0);
	grid_layout->addWidget(w,nRows,1);

}

void DialogPannel::HandleChanged(QString source,QString handle,QString value)
{
	QString cmd = QString("function=handle_set;source=%1;destin=%2;handle=%3;value=%4;")
			.arg(m_pCmd->toInt("instance",0))
			.arg(source)
			.arg(handle)
			.arg(value)
			;
	QByteArray arr = cmd.toUtf8();
	TASKBUS::push_subject(TB_SUBJECT_CMD,0,arr.size(),
						  (const unsigned char *)arr.constData()
						  );
}
