#include "pch.h"
#include "TsneSettings.h"
#include <QLineEdit>
#include <QSlider>
#include <QRegExp>


TsneSettings::TsneSettings(QWidget *parent)
	: QWidget(parent)
{
	readSettigns();
	//Layout 
	tsneSettings->setContentsMargins(0, 0, 0, 0);
	tsneSettings->addWidget(new QLabel("T-SNE Settings:"), 0, 0);
	tsneSettings->addWidget(new QLabel("   Perplexity"), 1, 0);
	tsneSettings->addWidget(new QLabel("   Lernrate"), 2, 0);
	
	perplexityEdit->setMinimumWidth(80);
	perplexityEdit->setMaximumWidth(80);
	perplexityEdit->setText(QString::number(perplexity));
	tsneSettings->addWidget(perplexityEdit, 1, 1);
	
	perplexitySlider->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Preferred);
	perplexitySlider->setValue(perplexity);
	perplexitySlider->setMinimum(perplexityMin);
	perplexitySlider->setMaximum(perplexityMax);
	perplexitySlider->setTickInterval((perplexityMax - perplexityMin + 1) / 10);
	perplexitySlider->setTickPosition(QSlider::TickPosition::TicksBelow);
	tsneSettings->addWidget(perplexitySlider, 1, 2);
	
	learnrateEdit->setMinimumWidth(80);
	learnrateEdit->setMaximumWidth(80);
	learnrateEdit->setText(QString::number(learnrate));
	tsneSettings->addWidget(learnrateEdit, 2, 1);
	
	learnrateSlider->setValue(learnrate);
	learnrateSlider->setMinimum(learnrateMin);
	learnrateSlider->setMaximum(learnrateMax);
	learnrateSlider->setTickInterval((learnrateMax - learnrateMin + 1) / 10);
	learnrateSlider->setTickPosition(QSlider::TickPosition::TicksBelow);
	learnrateSlider->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Preferred);
	tsneSettings->addWidget(learnrateSlider, 2, 2);
	

	QRegExp rxMinMax("[0-9]+");
	QRegExpValidator* validatorMinMax = new QRegExpValidator(rxMinMax, 0);
	learnrateEdit->setValidator(validatorMinMax);
	perplexityEdit->setValidator(validatorMinMax);

	connect(perplexitySlider, &QSlider::valueChanged, this, &TsneSettings::setPerplexity);
	connect(learnrateSlider, &QSlider::valueChanged, this, &TsneSettings::setLearnrate);
	connect(learnrateEdit, &QLineEdit::editingFinished, this, &TsneSettings::learnrateEditChangeEvent);
	connect(perplexityEdit, &QLineEdit::editingFinished, this, &TsneSettings::perplexityEditChangeEvent);
}

TsneSettings::~TsneSettings()
{
	writeSettings();
}

void TsneSettings::setPerplexity(int value)
{
	if (perplexity == value) return;
	perplexity = std::clamp(value, perplexityMin, perplexityMax);
	perplexitySlider->setValue(perplexity);
	perplexityEdit->setText(QString::number(perplexity));
	emit perplexityChanged(perplexity);
}

void TsneSettings::setLearnrate(int value)
{
	if (learnrate == value) return;
	learnrate = std::clamp(value, learnrateMin, learnrateMax);
	learnrateSlider->setValue(learnrate);
	learnrateEdit->setText(QString::number(learnrate));
	emit learnrateChanged(learnrate);
}

void TsneSettings::readSettigns()
{
	//Settings
	QSettings settings("settings.ini", QSettings::IniFormat, this);
	settings.beginGroup("Tsne");
	maxIter = settings.value("maxIter", 750).toInt();
	perplexity = settings.value("perplexity", 10).toInt();
	perplexityMin = settings.value("perplexity_MIN", 1).toInt();
	perplexityMax = settings.value("perplexity_MAX", 50).toInt();
	learnrate = settings.value("learnrate", 200).toInt();
	learnrateMin = settings.value("learnrate_MIN", 1).toInt();
	learnrateMax = settings.value("learnrate_MAX", 1000).toInt();
	settings.endGroup();
}

void TsneSettings::writeSettings()
{
	//Settings
	QSettings settings("settings.ini", QSettings::IniFormat, this);
	settings.beginGroup("Tsne");
	settings.setValue("maxIter", maxIter);
	settings.setValue("perplexity", perplexity);
	settings.setValue("perplexity_MIN", perplexityMin);
	settings.setValue("perplexity_MAX", perplexityMax);
	settings.setValue("learnrate", learnrate);
	settings.setValue("learnrate_MIN", learnrateMin);
	settings.setValue("learnrate_MAX", learnrateMax);
	settings.endGroup();
}

void TsneSettings::learnrateEditChangeEvent()
{
	bool success = false;
	int value = learnrateEdit->text().toInt(&success);
	if (success) {
		setLearnrate(value);
	}
}

void TsneSettings::perplexityEditChangeEvent()
{
	bool success = false;
	int value = perplexityEdit->text().toInt(&success);
	if (success) {
		setPerplexity(value);
	}
}
