#include "pch.h"
#include "RangeSlider.h"
#include <QDebug>
#include <QComboBox>

#include "util.h"

RangeSlider::RangeSlider(QWidget *parent)
	: QWidget(parent), sliderRangeColor(200,200,200), rangeColor(0,122,204)
{
	QVBoxLayout* layoutOuter = new QVBoxLayout(this);
	layoutOuter->setContentsMargins(0, 0, 0, 0);
	QHBoxLayout* buttonPanelLayout = new QHBoxLayout();
	buttonPanelLayout->setContentsMargins(0, 0, 0, 0);
	layoutOuter->addLayout(buttonPanelLayout);
	layoutOuter->insertStretch(1);
	titleLabel = new QLabel("Title");
	buttonPanelLayout->addWidget(titleLabel);
	buttonPanelLayout->insertStretch(1);
	
	QComboBox* combobox = new QComboBox(this);
	combobox->addItem("Range");
	combobox->addItem("Iteration");
	connect(combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
		this, [this](int index) {this->setMode((DisplayMode)index); });
	buttonPanelLayout->addWidget(combobox);
	this->setMaximumHeight(70);
	this->setMinimumHeight(70);
}

RangeSlider::~RangeSlider()
{
}

void RangeSlider::setMinSliderValue(int value)
{
	value = std::clamp(value, minRange, maxRange);
	if (value > maxSliderValue) {
		minSliderValue = maxSliderValue;
		maxSliderValue = value;
		emit minChanged(minSliderValue);
		emit maxChanged(maxSliderValue);
	}
	else {
		minSliderValue = value;
		emit minChanged(minSliderValue);
	}
}

void RangeSlider::setMaxSliderValue(int value)
{
	value = std::clamp(value, minRange, maxRange);
	if (value < minSliderValue) {
		maxSliderValue = minSliderValue;
		minSliderValue = value;
		emit minChanged(minSliderValue);
		emit maxChanged(maxSliderValue);
	}
	else {
		maxSliderValue = value;
		emit maxChanged(maxSliderValue);
	}
}

void RangeSlider::setItertionSliderValue(int value)
{
	value = std::clamp(value, minRange, maxRange);
	itertionSliderValue = value;
	emit minChanged(itertionSliderValue);
	emit maxChanged(itertionSliderValue);
}

void RangeSlider::setRange(int min, int max)
{
	if (min > max) {
		std::swap(min, max);
	}
	minRange = min;
	maxRange = max;
}

int RangeSlider::getMinRange() const
{
	return minRange;
}

int RangeSlider::getMaxRange() const
{
	return maxRange;
}

void RangeSlider::setMinRange(int value)
{
	if (value > maxRange) {
		minRange = maxRange;
		maxRange = value;
	}
	else {
		minRange = value;
	}
	emit minChanged(minSliderValue);
}

void RangeSlider::setMaxRange(int value)
{
	if (value < minRange) {
		maxRange = minRange;
		minRange = value;
	}
	else {
		maxRange = value;
	}
	emit maxChanged(maxSliderValue);
}

void RangeSlider::setMode(DisplayMode mode)
{
	this->mode = mode;
	switch (mode) {
	case Iteration:
		emit minChanged(itertionSliderValue);
		emit maxChanged(itertionSliderValue);
		break;
	default:
	case Range:
		emit minChanged(minSliderValue);
		emit maxChanged(maxSliderValue);
		break;
	}
	update();
}

void RangeSlider::setTitle(QString string)
{
	titleLabel->setText(string);
}

void RangeSlider::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);
	painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
	painter.setPen(sliderRangeColor);
	//painter.setBrush(sliderRangeColor);
	//FindMiddle
	int middle = 35;
	painter.drawRect(QRect(QPoint(minPos(), middle + 2), QPoint(maxPos(), middle - 2)));
	painter.setPen(Qt::black);
	painter.setFont(QFont("Arial", 8));
	QRect textRect(0, 0, 30, 9);
	textRect.moveCenter(QPoint(minPos(), middle + 20));
	painter.drawText(textRect, Qt::AlignCenter, QString::number(this->minRange, 'f', 0));
	textRect.moveCenter(QPoint(maxPos(), middle + 20));
	painter.drawText(textRect, Qt::AlignCenter, QString::number(this->maxRange, 'f', 0));
	
	

	
	//DrawSlider
	QPen pen(rangeColor);
	pen.setWidth(2);
	painter.setPen(pen);
	painter.setBrush(sliderRangeColor);
	switch (mode) {
	case Iteration:
	{
		double itertionSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, itertionSliderValue);
		double itertionSliderPos = util::linearInterpolate(minPos(), maxPos(), itertionSliderAlpha);

		painter.drawEllipse(QPointF(itertionSliderPos, (double)middle + 1), 10, 10);
		painter.setPen(Qt::black);
		textRect.moveCenter(QPoint(itertionSliderPos, middle + 20));
		painter.drawText(textRect, Qt::AlignCenter, QString::number(this->itertionSliderValue, 'f', 0));
		break;
	}
	default:
	case Range:
	{
		double minSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, minSliderValue);
		double minSliderPos = util::linearInterpolate(minPos(), maxPos(), minSliderAlpha);

		double maxSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, maxSliderValue);
		double maxSliderPos = util::linearInterpolate(minPos(), maxPos(), maxSliderAlpha);
		//DrawRange
		painter.fillRect(QRectF(QPointF(minSliderPos, (double)middle - 2), QPointF(maxSliderPos, (double)middle + 2)), rangeColor);
		painter.drawEllipse(QPointF(minSliderPos, (double)middle + 1), 10, 10);
		painter.drawEllipse(QPointF(maxSliderPos, (double)middle + 1), 10, 10);
		painter.setPen(Qt::black);
		textRect.moveCenter(QPoint(minSliderPos, middle + 20));
		painter.drawText(textRect, Qt::AlignCenter, QString::number(this->minSliderValue, 'f', 0));
		textRect.moveCenter(QPoint(maxSliderPos, middle + 20));
		painter.drawText(textRect, Qt::AlignCenter, QString::number(this->maxSliderValue, 'f', 0));
		break;
	}
	}
}

void RangeSlider::mouseMoveEvent(QMouseEvent* event)
{
	if (childAt(event->pos()) != nullptr) {
		return;
	}
	updateSliderPosition(event);
}

void RangeSlider::mousePressEvent(QMouseEvent* event)
{
	if (childAt(event->pos()) != nullptr) {
		return;
	}
	updateSliderPosition(event);
}


void RangeSlider::updateSliderPosition(QMouseEvent* event)
{
	
	
	
	//pos to alpha
	double alpha = util::inverseLinearInterpolation(minPos(), maxPos(), event->pos().x());
	double minSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, minSliderValue);
	double maxSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, maxSliderValue);



	double value = util::linearInterpolate(minRange, maxRange, alpha);
	switch (mode) {
	case Iteration:
		setItertionSliderValue(value);
		break;
	default:
	case Range:
		double distanceToMin = std::abs(minSliderValue - value);
		double distanceToMax = std::abs(maxSliderValue - value);
		if (distanceToMin < distanceToMax) {
			setMinSliderValue(value);
		}
		else {
			setMaxSliderValue(value);
		}
		break;
	}
	
	update();
}

int RangeSlider::maxPos()
{
	return rect().right() - 11;
}

int RangeSlider::minPos()
{
	return rect().left() + 11;
}

