#include "pch.h"
#include "Bitfield.h"
#include <QSlider>
#include <QTimer>
#include <QCursor>


Bitfield::Bitfield(QWidget *parent)
	: SearchSpacePlott(parent)
{
	setAxisLegend("Position", "#SetBits");
}

Bitfield::~Bitfield()
{
	
}

void Bitfield::frameGraphInView()
{
	setVisibleWindow(0, 1, 0, maxAmountOfSetBits);
	window.ZoomOut(0.05);
	update();
}



void Bitfield::drawData(QPainter& painter)
{
	painter.setPen(Qt::lightGray);
	painter.setBrush(Qt::Dense4Pattern);
	painter.drawRect(this->getDisplayRect());
	painter.setPen(Qt::black);
	painter.setBrush(Qt::NoBrush);
	painter.fillRect(QRectF(transformGraphToView(QPointF(0, maxAmountOfSetBits)), transformGraphToView(QPointF(1, 0))), Qt::white);
	painter.drawRect(QRectF(transformGraphToView(QPointF(0, maxAmountOfSetBits)), transformGraphToView(QPointF(1, 0))));

	//Draw Dots
	QPen linePen;
	QRect graphDisplayRect = getDisplayRect();
	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);

	for (const GraphPlottSeries& graphSeries : seriesVec) {
		if (!graphSeries.data) {
			qDebug() << "Pointer to nothing pls help";
			continue;
		}
		if (graphSeries.data->empty() || graphSeries.hide) continue;
		linePen.setWidth(2);
		linePen.setColor(Qt::transparent);
		painter.setPen(linePen);
		for (auto data : *graphSeries.data) {
			if (data.orginalPoint->iteration < minIter) {
				continue;
			}
			if (data.orginalPoint->iteration > maxIter) {
				break;
			}
			QColor color = data.color;
			color.setAlphaF(this->transparentAlphaValue);
			linePen.setColor(Qt::transparent);
			painter.setPen(linePen);
			painter.setBrush(color);
			if (window.inBound(data.toQPointF())) {
				painter.drawEllipse(transformGraphToView(data.toQPointF(), stregth_factorX, stregth_factorY, translation), circleSize, circleSize);
			}
		}
		painter.setBrush(Qt::BrushStyle::NoBrush);
	}
}





void Bitfield::searchForPointUnderCursor()
{
	//check if mouse stayed still
	QPoint globalPosition = QCursor::pos();
	QPointF pos = this->mapFromGlobal(globalPosition);

	if (pos != lastPosition){
		return;
	}
	if (seriesVec.empty() || seriesVec[0].data->empty()) {
		return;
	}
	QRect graphDisplayRect = getDisplayRect();
	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);

	const GraphDataPoint* min = &seriesVec[0].data->at(0);
	double minSqaredDistance = sqaredDistance(transformGraphToView(min->toQPointF(), stregth_factorX, stregth_factorY, translation), pos);
	std::vector<GraphPlottSeries>::iterator actualBestSeries = seriesVec.begin();
	for (auto seriesIter = seriesVec.begin(); seriesIter != seriesVec.end(); seriesIter++) {
		for (const GraphDataPoint& point : *seriesIter->data) {
			if (point.orginalPoint->iteration < minIter) {
				continue;
			}
			if (point.orginalPoint->iteration > maxIter) {
				break;
			}
			double distance = sqaredDistance(transformGraphToView(point.toQPointF(), stregth_factorX, stregth_factorY, translation), pos);
			if (distance < minSqaredDistance) {
				minSqaredDistance = distance;
				min = &point;
				actualBestSeries = seriesIter;
			}
		}
	}
	//if curser is radius + 3pixel away
	if (minSqaredDistance <= circleSize * circleSize + 9) {
		QPointF pointInWidget = transformGraphToView(min->toQPointF(), stregth_factorX, stregth_factorY, translation);
		QToolTip::showText(this->mapToGlobal(QPoint(pointInWidget.x(), pointInWidget.y())) - QPoint(0, 35), QString::fromStdString(min->orginalPoint->bitstringToStdString()));
	}
}

void Bitfield::addPointsInWindowToScratchPad(VisibleWindow& window)
{
	if (!pad) {
		qDebug() << "NoPad";
		return;
	}
	for (auto seriesIter = seriesVec.begin(); seriesIter != seriesVec.end(); seriesIter++) {
		if (seriesIter->hide) continue;
		for (const GraphDataPoint& point : *seriesIter->data) {
			if (point.orginalPoint->iteration < minIter) {
				continue;
			}
			if (point.orginalPoint->iteration > maxIter) {
				break;
			}
			if (window.inBound(point.toQPointF()) && point.existLink()) {
				pad->addPoint(*point.orginalPoint);
			}
		}
	}
}


