#include <QTimer>
#include "graphic_ranges.h"


GraphicRanges::GraphicRanges(QWidget * parent): Graphic(parent) {
	connect(this, SIGNAL(graphicPaintEvent(QPainter *)), this, SLOT(onPaintEvent(QPainter *)));
	connect(this, SIGNAL(graphicMousePressEvent(QPointF, int)), this, SLOT(onMousePressEvent(QPointF, int)));
	connect(this, SIGNAL(graphicMouseMoveEvent(QPointF, int)), this, SLOT(onMouseMoveEvent(QPointF, int)));
	connect(this, SIGNAL(graphicMouseReleaseEvent(QPointF, int)), this, SLOT(onMouseReleaseEvent(QPointF, int)));
	//setOpenGL(true);
	range_start = range_end = 0.;
	range_sel = request = false;
	color_ = QColor(64, 192, 64, 128);
	color_cur = QColor(64, 64, 192, 128);
}


GraphicRanges::~GraphicRanges() {
}


int GraphicRanges::addRange(double start, double end, QString name, QColor color) {
	ranges_ << Range(start, end, name, color);
	update();
	return ranges_.size() - 1;
}


void GraphicRanges::replaceRange(int index, double start, double end) {
	if (index < 0 || index >= ranges_.size()) return;
	ranges_[index].start = start;
	ranges_[index].end = end;
	update();
}


GraphicRanges::Range GraphicRanges::removeRange(int index) {
	if (index < 0 || index >= ranges_.size()) return Range();
	Range ret = ranges_.takeAt(index);
	update();
	return ret;
}


void GraphicRanges::clearRanges() {
	ranges_.clear();
	update();
}


void GraphicRanges::clearRangesByColor(QColor c) {
	for (int i = 0; i < ranges_.size(); ++i) {
		if (ranges_[i].color == c) {
			ranges_.removeAt(i);
			--i;
		}
	}
	update();
}


GraphicRanges::Range GraphicRanges::rangeAll() const {
	Range ret;
	for (int g = 0; g < graphicsCount(); ++g) {
		const QPolygonF & gd(graphics[g].polyline);
		if (!gd.isEmpty()) {
			if (ret.isEmpty()) {
				ret.start = gd.front().x();
				ret.end   = gd.back ().x();
			} else {
				ret.start = qMin(ret.start, gd.front().x());
				ret.end   = qMax(ret.end  , gd.back ().x());
			}
		}
	}
	return ret;
}


GraphicRanges::Range GraphicRanges::rangeVisible() const {
	Range ret;
	ret.start = visualRect().left ();
	ret.end   = visualRect().right();
	return ret;
}


void GraphicRanges::setCurrentRange(double start, double end) {
	range_start = start;
	range_end = end;
	update();
}


void GraphicRanges::clearCurrentRange() {
	range_start = range_end = 0.;
	update();
}


GraphicRanges::Range GraphicRanges::currentRange() const {
	return Range(range_start, range_end);
}


void GraphicRanges::clear() {
	ranges_.clear();
	Graphic::clear();
}


void GraphicRanges::drawRange(QPainter * p, const GraphicRanges::Range & r, QColor color) {
	if (r.isEmpty()) return;
	double cx[2] = {real2canvasX(r.start),
					real2canvasX(r.end)};
	p->fillRect(QRectF(cx[0], 0, cx[1] - cx[0], height()), color);
	p->setPen(QPen(QColor(color.rgb()), 2, Qt::DotLine));
	p->drawLine(cx[0], 0, cx[0], height());
	p->drawLine(cx[1], 0, cx[1], height());
	if (!r.name.isEmpty()) {
		p->setPen(QPen(QColor(color.rgb()).darker(), 1, Qt::SolidLine));
		p->drawText(QRectF(cx[0], 10, cx[1] - cx[0], height() - 10), Qt::AlignHCenter | Qt::AlignTop | Qt::TextDontClip, r.name);
	}

}


void GraphicRanges::onPaintEvent(QPainter * p) {
	p->save();
	//QPen pen = p->pen();
	for (const auto & r: ranges_) {
		drawRange(p, r, r.hasColor() ? r.color : color_);
	}
	drawRange(p, Range(range_start, range_end), color_cur);
	p->restore();
}


void GraphicRanges::onMousePressEvent(QPointF p, int b) {
	if (b == Qt::RightButton) return;// request = false;
	if (b != Qt::LeftButton || !request) return;
	update();
	range_sel = true;
	range_start = range_end = p.x();
	setNavigationEnabled(false);
}


void GraphicRanges::onMouseMoveEvent(QPointF p, int b) {
	if (!range_sel) return;
	range_end = p.x();
	update();
}


void GraphicRanges::onMouseReleaseEvent(QPointF p, int b) {
	if (b == Qt::RightButton && range_sel)
		canvas->setCursor(Qt::SplitHCursor);
	if (b != Qt::LeftButton) return;
	if (range_sel) {
		range_sel = request = false;
		range_end = p.x();
		if (range_start > range_end)
			std::swap(range_start, range_end);
		rangeSelected(range_start, range_end);
		canvas->setCursor(Qt::ArrowCursor);
		range_start = range_end = 0.;
	}
	QTimer::singleShot(10, [this](){setNavigationEnabled(true); update();});
}


void GraphicRanges::rangeRequest() {
	request = true;
	canvas->setCursor(Qt::SplitHCursor);
}


void GraphicRanges::cancelRangeRequest(bool with_nav) {
	request = false;
	canvas->setCursor(Qt::ArrowCursor);
	if (with_nav)
		QTimer::singleShot(10, [this](){setNavigationEnabled(true); update();});
}
