#include "mainwindow.h"

#include "piqt.h"
#include "qad_locations.h"


MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() {
	setupUi(this);
	active_ = false;
	lineInput->setFocus();
#if QT_VERSION >= 0x050000
	treeGraphics->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
	treeGraphics->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
#else
	treeGraphics->header()->setResizeMode(0, QHeaderView::ResizeToContents);
	treeGraphics->header()->setResizeMode(1, QHeaderView::ResizeToContents);
#endif
	npal = epal = lineInput->palette();
	epal.setColor(lineInput->backgroundRole(), QColor(Qt::red).lighter(150));
	connect(&session, SIGNAL(loading(QPIConfig &)), this, SLOT(loading(QPIConfig &)));
	connect(&session, SIGNAL(saving(QPIConfig &)), this, SLOT(saving(QPIConfig &)));
	session.setFile(QAD::userPath(QAD::ltConfig, "session_qpicalc"));
	session.addEntry(this);
	session.addEntry(lineInput);
	session.addEntry(tabWidget);
	session.load();
	ans = evaluator.setVariable("ans");
	on_lineInput_returnPressed();
}


MainWindow::~MainWindow() {
	session.save();
}


void MainWindow::changeEvent(QEvent * e) {
	QMainWindow::changeEvent(e);
	switch (e->type()) {
	case QEvent::LanguageChange: retranslateUi(this); break;
	default: break;
	}
}


void MainWindow::updateGraphics() {
	graphic->setGraphicsCount(treeGraphics->topLevelItemCount());
	for (int i = 0; i < treeGraphics->topLevelItemCount(); ++i)
		graphic->setGraphicColor(treeGraphics->topLevelItem(i)->data(0, Qt::DecorationRole).value<QColor>(), i);
	redrawGraphics();
}


void MainWindow::redrawGraphics() {
	QRectF sr = graphic->visualRect();
	double dx = (sr.right() - sr.left()) / graphic->width(), sx = sr.left(), fx = sr.right(), cx;
	QPolygonF pol;
	evaluator.setVariable("x");
	int vi = evaluator.variableIndex("x");
	graphic->setAutoUpdate(false);
	for (int i = 0; i < treeGraphics->topLevelItemCount(); ++i) {
		QTreeWidgetItem * ti = treeGraphics->topLevelItem(i);
		graphic->setGraphicName(ti->text(1), i);
		pol.clear();
		if (ti->checkState(0) == Qt::Checked) {
			if (evaluator.check(Q2PIString(ti->text(1)))) {
				cx = sx;
				while (cx < fx) {
					evaluator.setVariable(vi, complexd(cx, 0.));
					pol << QPointF(cx, evaluator.evaluate().real());
					cx += dx;
				}
			}
		}
		graphic->setGraphicVisible(ti->checkState(0) == Qt::Checked, i);
		graphic->setGraphicData(pol, i);
	}
	graphic->setAutoUpdate(true);
	graphic->updateGraphics();
}


void MainWindow::loading(QPIConfig & conf) {
	active_          = false;
	QStringList vars = conf.getValue("variables").toStringList();
	int vc           = vars.size() / 2;
	for (int i = 0; i < vc; ++i) {
		QTreeWidgetItem * ti = new QTreeWidgetItem(treeVariables);
		ti->setText(0, vars[i * 2]);
		ti->setText(1, vars[i * 2 + 1]);
		ti->setFlags(ti->flags() | Qt::ItemIsEditable);
		treeVariables->addTopLevelItem(ti);
	}
	buttonVarClear->setEnabled(treeVariables->topLevelItemCount() > 0);
	QByteArray ba = conf.getValue("graphics").toByteArray();
	QDataStream s(ba);
	QVector<GraphicType> g;
	if (!ba.isEmpty()) s >> g;
	graphic->setAllGraphics(g);
	for (int i = 0; i < graphic->graphicsCount(); ++i) {
		graphic->setCurrentGraphic(i);
		QTreeWidgetItem * ti = new QTreeWidgetItem(treeGraphics);
		ti->setFlags(ti->flags() | Qt::ItemIsEditable);
		ti->setCheckState(0, graphic->graphicVisible() ? Qt::Checked : Qt::Unchecked);
		ti->setData(0, Qt::DecorationRole, graphic->graphicColor());
		ti->setText(1, graphic->graphicName());
		treeGraphics->addTopLevelItem(ti);
	}
	buttonGraphicClear->setEnabled(treeGraphics->topLevelItemCount() > 0);
	graphic->setVisualRect(conf.getValue("graphicRect", QRectF(-1., -1., 2., 2.)).toRectF());
	ba = conf.getValue("graphic_state").toByteArray();
	if (!ba.isEmpty()) graphic->load(ba);
	on_tabWidget_currentChanged(0);
	redrawGraphics();
	active_ = true;
}


void MainWindow::saving(QPIConfig & conf) {
	QStringList vars;
	int vc = treeVariables->topLevelItemCount();
	for (int i = 0; i < vc; ++i) {
		QTreeWidgetItem * ti = treeVariables->topLevelItem(i);
		vars << ti->text(0) << ti->text(1);
	}
	conf.setValue("variables", vars);

	QVector<GraphicType> g;
	vc = treeGraphics->topLevelItemCount();
	for (int i = 0; i < vc; ++i) {
		QTreeWidgetItem * ti = treeGraphics->topLevelItem(i);
		vars << QString::number(ti->background(1).color().rgb()) << ti->text(2);
	}
	QByteArray ba;
	QDataStream s(&ba, QIODevice::WriteOnly);
	s << graphic->allGraphics();
	conf.setValue("graphics", QByteArray2QString(ba));
	conf.setValue("graphicRect", graphic->visualRect());
	conf.setValue("graphic_state", graphic->save());
}


void MainWindow::on_lineInput_textChanged(QString text) {
	if (evaluator.check(Q2PIString(text)))
		lineInput->setPalette(npal);
	else
		lineInput->setPalette(epal);
	labelParsed->setText(PI2QString(evaluator.expression()));
	labelError->setText(PI2QString(evaluator.error()));
}


void MainWindow::on_lineInput_returnPressed() {
	bool ret = evaluator.check(Q2PIString(lineInput->text()));
	if (ret)
		lineInput->setPalette(npal);
	else
		lineInput->setPalette(epal);
	labelParsed->setText(PI2QString(evaluator.expression()));
	labelError->setText(PI2QString(evaluator.error()));
	if (!ret) return;
	complexd val = evaluator.evaluate();
	evaluator.setVariable(ans, val);
	if (val.imag() == 0)
		labelResult->setText(QString::number(val.real()));
	else {
		if (val.real() == 0)
			labelResult->setText(QString::number(val.imag()) + "i");
		else {
			if (val.imag() > 0)
				labelResult->setText(QString::number(val.real()) + " + " + QString::number(val.imag()) + "i");
			else
				labelResult->setText(QString::number(val.real()) + " - " + QString::number(fabs(val.imag())) + "i");
		}
	}
	if (lineInput->text().trimmed().isEmpty()) return;
	QTreeWidgetItem *ti = 0, *pti = 0;
	if (treeHistory->topLevelItemCount() > 0) pti = treeHistory->topLevelItem(treeHistory->topLevelItemCount() - 1);
	if (pti != 0)
		if (pti->text(0) == lineInput->text()) return;
	ti = new QTreeWidgetItem(treeHistory);
	ti->setText(0, lineInput->text());
	ti->setText(1, labelResult->text());
	treeHistory->addTopLevelItem(ti);
	if (treeHistory->verticalScrollBar()->value() == treeHistory->verticalScrollBar()->maximum()) treeHistory->scrollToBottom();
}


void MainWindow::on_treeGraphics_itemSelectionChanged() {
	buttonGraphicDel->setDisabled(treeGraphics->selectedItems().isEmpty());
	if (treeGraphics->currentItem()) {
		int ind = treeGraphics->indexOfTopLevelItem(treeGraphics->currentItem());
		if (ind < 0 || ind >= graphic->graphicsCount()) return;
		graphic->setCurrentGraphic(ind);
	}
}


void MainWindow::on_treeGraphics_itemDoubleClicked(QTreeWidgetItem * item, int column) {
	Qt::ItemFlags f = item->flags();
	if (column != 1)
		f &= ~Qt::ItemIsEditable;
	else
		f |= Qt::ItemIsEditable;
	item->setFlags(f);
	if (column != 0) return;
	QColor col = QColorDialog::getColor(item->data(0, Qt::DecorationRole).value<QColor>(),
										this,
										"Select color for graphic",
										QColorDialog::ShowAlphaChannel);
	if (!col.isValid()) return;
	item->setData(0, Qt::DecorationRole, col);
	updateGraphics();
}


void MainWindow::on_buttonVarAdd_clicked() {
	QTreeWidgetItem * ti = new QTreeWidgetItem(treeVariables);
	ti->setSelected(true);
	ti->setFlags(ti->flags() | Qt::ItemIsEditable);
	treeVariables->addTopLevelItem(ti);
	treeVariables->setFocus();
	treeVariables->editItem(ti);
	buttonVarClear->setEnabled(treeVariables->topLevelItemCount() > 0);
}


void MainWindow::on_buttonVarDel_clicked() {
	QList<QTreeWidgetItem *> si = treeVariables->selectedItems();
	foreach(QTreeWidgetItem * i, si)
		delete i;
	buttonVarClear->setEnabled(treeVariables->topLevelItemCount() > 0);
}


void MainWindow::on_buttonGraphicAdd_clicked() {
	graphic->setGraphicsCount(graphic->graphicsCount() + 1);
	graphic->setCurrentGraphic(graphic->graphicsCount() - 1);
	QTreeWidgetItem * ti = new QTreeWidgetItem(treeGraphics);
	ti->setSelected(true);
	ti->setFlags(ti->flags() | Qt::ItemIsEditable);
	ti->setCheckState(0, Qt::Checked);
	ti->setData(0, Qt::DecorationRole, graphic->graphicColor());
	treeGraphics->addTopLevelItem(ti);
	treeGraphics->setFocus();
	treeGraphics->editItem(ti, 1);
	buttonGraphicClear->setEnabled(treeGraphics->topLevelItemCount() > 0);
	updateGraphics();
}


void MainWindow::on_buttonGraphicDel_clicked() {
	QList<QTreeWidgetItem *> si = treeGraphics->selectedItems();
	foreach(QTreeWidgetItem * i, si)
		delete i;
	buttonGraphicClear->setEnabled(treeGraphics->topLevelItemCount() > 0);
	updateGraphics();
}


void MainWindow::on_buttonGraphicClear_clicked() {
	treeGraphics->clear();
	buttonGraphicClear->setEnabled(false);
	updateGraphics();
}


void MainWindow::on_tabWidget_currentChanged(int index) {
	PIEvaluator eval;
	evaluator.clearCustomVariables();
	for (int i = 0; i < treeVariables->topLevelItemCount(); ++i) {
		QString vn, vv;
		vn = treeVariables->topLevelItem(i)->text(0);
		vv = treeVariables->topLevelItem(i)->text(1);
		eval.check(Q2PIString(vv));
		evaluator.setVariable(Q2PIString(vn), eval.evaluate());
	}
	if (index == 0) on_lineInput_returnPressed();
	if (index == 2) redrawGraphics();
}
