#include "pch.h"
#include "tsneIteractive.h"
#include <QDebug>
#include <thread>
#include <future>
#include <chrono>

#include "src/t_sne/tsne.h"
#include "tSneAlgo.h"

tsneIteractive::tsneIteractive(QWidget *parent)
	: QWidget(parent), view(new GraphView(this, Bound(-50,50,-50,50))), gradient(new ColorGradient(this))
{
	ui.setupUi(this);
	ui.verticalLayout->insertWidget(0, view);
	view->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
	ui.verticalLayout->addWidget(gradient);
	//ui.gridLayout->addWidget(gradient, 4, 0);
	//ui.gridLayout->addWidget(gradient, 4, 0, 1, 4);
	view->setUseFixedBound(true);
	connect(timer, &QTimer::timeout, this, static_cast<void (tsneIteractive::*)()>(&tsneIteractive::updateCanvasIfAlgoRuns));
	connect(ui.startButton, &QPushButton::pressed,
		this, &tsneIteractive::startRun);
	connect(ui.pauseButton, &QPushButton::pressed,
		this, &tsneIteractive::pauseRun);
	connect(gradient, &ColorGradient::gradientChanged, this, &tsneIteractive::updateViewGradient);
	ui.perplexitySlider->setMinimum(1);
	ui.perplexitySlider->setMaximum(50);
	ui.perplexitySlider->setValue(20);
	ui.perplexityLineEdit->setText(QString::number(20));
	ui.learnrateSlider->setMinimum(1);
	ui.learnrateSlider->setMaximum(1000);
	ui.learnrateSlider->setValue(200);
	ui.learnrateLineEdit->setText(QString::number(200));
	connect(ui.learnrateSlider, &QSlider::valueChanged, this, [this](int value){
		ui.learnrateSlider->setToolTip(QString::number(value));
		ui.learnrateLineEdit->setText(QString::number(value));
		if (tsneConcurrent != nullptr) {
			this->tsneConcurrent->setLearningRate(value);
		}
		});
	connect(ui.perplexitySlider, &QSlider::valueChanged, this, [this](int value) {
		ui.perplexitySlider->setToolTip(QString::number(value));
		ui.perplexityLineEdit->setText(QString::number(value));
		if (tsneConcurrent != nullptr) {
			this->tsneConcurrent->setPerplexity(value);
		}
		});
	ui.progressBar->setMinimum(0);
	ui.progressBar->setMaximum(750);
	ui.progressBar->setValue(0);
	
}

tsneIteractive::~tsneIteractive()
{
	if (tsneConcurrent != nullptr) {
		delete tsneConcurrent;
	}
}

void tsneIteractive::assignRunData(RunData* data)
{
	this->data = data;
}

tSneAlgo* tsneIteractive::getTsneConcurrent()
{
	return tsneConcurrent;
}

void tsneIteractive::updateCanvasIfAlgoRuns()
{
	if (tsneConcurrent->actualIteration >= 750) {
		timer->stop();
	}
	ui.progressBar->setValue(tsneConcurrent->actualIteration);
	//view->autoZoomOut();
	view->update();
	ui.iterLabel->setText(QString("Iteration: ") + QString::number(tsneConcurrent->actualIteration));
}

void tsneIteractive::updateViewGradient()
{
	view->updateGraphColors(*gradient);
	update();
}

void tsneIteractive::pauseRun()
{
	qDebug() << "Pause";
	tsneConcurrent->pause();
	if (timer->isActive()) {
		timer->stop();
	}
	else {
		timer->start();
	}
}

void tsneIteractive::startRun()
{
	if (data == nullptr) {
		qDebug() << "NoData!";
		return;
	}
	double* Y = nullptr;
	double** X = &Y;
	if (tsneConcurrent != nullptr) {
		delete tsneConcurrent;
	}
	tsneConcurrent = new tSneAlgo(data->solutionVec.begin(), data->solutionVec.end(), X, 20, 200, 750);
	tsneConcurrent->start();
	qDebug() << "Y:" << Y;
	view->addYMatrix(Y, data->solutionVec);
	view->updateGraphColors(*gradient);
	view->update();
	timer->start(34);

}
