#include <QtGui>

#include "PlotScene.h"
#include <iostream>

typedef unsigned int uint;

void PlotScene::setDefaults(){
	selected=-1;		// None
	signalNum=0;
	showGrip=true;
	gripSpace=50;
	border=10;
	//XStep=1;
	YStep=1;
	
	// Colors
	gripColor = new QColor(Qt::darkCyan);
	axesColor = new QColor(Qt::green);
	bgColor = new QColor(Qt::black);
	QBrush bg(*bgColor);
	setBackgroundBrush(bg);
	
	//Signals
	colors[0] = QColor(Qt::red);
	colors[1] = QColor(Qt::blue);
	colors[2] = QColor(Qt::cyan);
	colors[3] = QColor(Qt::lightGray);
}


PlotScene::PlotScene( qreal width, qreal height, QObject * parent) 
	: QGraphicsScene(-width/2,-height/2,width,height,parent) {
	setDefaults();
	createMenus();
	drawGrip();
	drawAxes();

}

PlotScene::PlotScene( qreal width, qreal height,QString &filename, QObject * parent) 
	: QGraphicsScene(-width/2,-height/2,width,height,parent) {
	setDefaults();
	createMenus();
	loadSignal(filename);
}

PlotScene::~PlotScene(){}

// Public Methods
void PlotScene::setForeColor(QColor & c){*foreColor=c;}
void PlotScene::setBgColor(QColor & c){*bgColor=c;}
void PlotScene::setGripColor(QColor & c){*gripColor=c;}
void PlotScene::setAxesColor(QColor & c){*axesColor=c;}
void PlotScene::setSelectedSignal(int i){selected=i;}

QColor & PlotScene::getForeColor()const {return *foreColor;}
Signal PlotScene::getSignal(int index) {return Signals[index];}
QColor & PlotScene::getSignalColor(int index) {return colors[index];}
int PlotScene::getSelectedSignal(){return selected;}

bool PlotScene::loadSignal(QString &filename){
	if (signalNum==MAX_SIG_NUM){
		QMessageBox::critical(((QWidget *)parent()),"E R R O R","There are too many Signals in this plot.\nYou have to Create a new one... Sorry...");
		return false;
	
	}

	Signal tmp=Signal(filename.toStdString().c_str());
	if (tmp.size()<1) return false;

	// Check if it is the first
	if (selected==-1) selected=0;

	Signals[signalNum]=tmp;
	signalNum++;	
	clearScene();
	resizeRectCalcStep();
	drawGrip();
	drawAxes();
	for (int i=0; i<signalNum; i++) drawSignal(Signals[i],colors[i]);
	return true;
}

void PlotScene::redrawScene(){
	clearScene();
	resizeRectCalcStep();
	drawGrip();
	drawAxes();
	for (int i=0; i<signalNum; i++) drawSignal(Signals[i],colors[i]);
}

// Drawing -----------------------
void PlotScene::drawGrip(){
	
	if (!showGrip) return;
	
	QRectF srect = sceneRect();
	QPen pen(*gripColor,1);
	
	// VR
	// >0
	for (qreal i=gripSpace; i<srect.right(); i+=gripSpace){
		QLineF l(i,srect.top(),i,srect.bottom());
		addLine(l, pen)->setZValue(GRIP_Z);
	}
	// <0
	for (qreal i=-gripSpace; i>srect.left(); i-=gripSpace){
		QLineF l(i,srect.top(),i,srect.bottom());
		addLine(l, pen)->setZValue(GRIP_Z);
	}
	
	// HR
	// <0
	for (qreal i=gripSpace; i<srect.bottom(); i+=gripSpace){
		QLineF l(srect.left(),i,srect.right(),i);
		addLine(l, pen)->setZValue(GRIP_Z);
	}
	
	// >0
	for (qreal i=-gripSpace; i>srect.top(); i-=gripSpace){
		QLineF l(srect.left(),i,srect.right(),i);
		addLine(l, pen)->setZValue(GRIP_Z);
	}
}

void PlotScene::drawAxes(){
	QRectF srect = sceneRect();
		
	QLineF x(srect.left(),0,srect.right(),0);
	QLineF y(0,srect.top(),0,srect.bottom());
	
	QPen pen(*axesColor,1);	
	addLine(x, pen)->setZValue(AXES_Z);
	addLine(y, pen)->setZValue(AXES_Z);
}

QPointF & PlotScene::toRealXY(Point & p) const{
	return *(new QPointF(YStep*p.x,-YStep*p.y));
}

void PlotScene::resizeRectCalcStep(){
	double maxy=totalMaxY();
	double maxx=totalMaxX();
	double miny=totalMinY();
	double minx=totalMinX();

	YStep=(height()-2*border)/fabs(maxy-miny);

	// Resize Scene
	qreal posx=minx*YStep-border;
	qreal posy=-fabs(maxy*YStep)-border;
	qreal w=fabs(maxx-minx)*YStep+2*border;
	qreal h=fabs(maxy-miny)*YStep+2*border;

	QRectF newrect(posx,posy,w,h);
	setSceneRect (newrect);
}

void PlotScene::drawSignal(Signal &sig, QColor &col){

	if (sig.size()<1) return;

	// Draw Signal
	QPointF lastPoint=toRealXY(sig[0]);
	
	QPen pen(col,1);
	
	for (uint i=1; i<sig.size(); i++){
		QPointF nextPoint=toRealXY(sig[i]);
		QLineF l(lastPoint,nextPoint);
		lastPoint=nextPoint;
		QGraphicsItem * item=addLine(l,pen);
		//Last Drawn->on top
		item->setZValue(SIGNAL_Z+signalNum);
		char tip[50];
		tip[0]='\0';
		sprintf(tip,"x: %f\ny: %f",sig[i].x,sig[i].y);
		item->setToolTip(tip);
	}

	actionSave->setEnabled(true);
}

void PlotScene::clearScene(){
	// Clear Everything
	QList<QGraphicsItem *> list =items();
	
	QList<QGraphicsItem *>::Iterator it = list.begin();
	for (; it != list.end(); ++it) {
		if ( *it )
		delete *it;
	}
}

// End Of Drawing-----
//

// total Max n Min
double PlotScene::totalMaxY(){
	double max=Signals[0].getMaxY();
	
	for(int i=1; i<signalNum; i++)
		if (Signals[i].getMaxY() > max) max=Signals[i].getMaxY();

	return max;
}

double PlotScene::totalMinY(){
	double min=Signals[0].getMinY();
	
	for (int i=1; i<signalNum; i++)
		if (Signals[i].getMinY()<min) min=Signals[i].getMinY();
		
	return min;
}

double PlotScene::totalMaxX(){
	double max=Signals[0].getMaxX();
	
	for (int i=1; i<signalNum; i++)
		if (Signals[i].getMaxX()>max) max=Signals[i].getMaxX();
		
	return max;
}

double PlotScene::totalMinX(){
	double min=Signals[0].getMinX();
	
	for (int i=1; i<signalNum; i++)
		if (Signals[i].getMinX()<min) min=Signals[i].getMinX();
		
	return min;
}


void PlotScene::createMenus(){
	// PopUp Menu
	PlotPopUp=new QMenu;
		// Actions    
	actionLoad = new QAction(this);
	actionLoad->setText(QApplication::translate("MainWin", "&Load Signal", 0, QApplication::UnicodeUTF8));
	connect(actionLoad,SIGNAL(triggered()),this,SLOT(load()));
    
	actionSave = new QAction(this);
	actionSave->setText(QApplication::translate("MainWin", "&Save Selected Signal", 0, QApplication::UnicodeUTF8));
	actionSave->setEnabled(false);
	connect(actionSave,SIGNAL(triggered()),this,SLOT(save()));
	
	actionToggleGrip = new QAction(this);
	actionToggleGrip->setCheckable(true);
	actionToggleGrip->setChecked(true);
	actionToggleGrip->setText(QApplication::translate("MainWin", "&Show Grip", 0, QApplication::UnicodeUTF8));
	connect(actionToggleGrip,SIGNAL(triggered()),this,SLOT(toggleGrip()) );
    
	PlotPopUp->addAction(actionLoad);
	PlotPopUp->addAction(actionSave);
	PlotPopUp->addSeparator();
	PlotPopUp->addAction(actionToggleGrip);
}

// Events Override

void PlotScene::contextMenuEvent(QGraphicsSceneContextMenuEvent  * event){
	PlotPopUp->exec(event->screenPos());
}

void PlotScene::paintEvent(QPaintEvent *){}

// Public Slots
void PlotScene::toggleGrip(){
	if (showGrip) actionToggleGrip->setChecked(false);
	else actionToggleGrip->setChecked(true);
	
	showGrip=!showGrip;
	
	// Redraw
	redrawScene();
}


void PlotScene::load(){
	
	//File Dialog
	QFileDialog dialog((QWidget *)parent(),tr("Load Signal From File"));
	
	// Initial Directory
	QString dir="/home";
	
	#ifdef Q_OS_WIN32 
		dir="C:\\";
	#endif
	
	dialog.setDirectory(dir);
	
	// File Extension Filters
	 QStringList filters;
		filters << "DAT Files (*.dat *.data)"
				<< "Sig Files (*.sig )"
				<< "Any files (*.*)";
	
	dialog.setFilters(filters);
	dialog.setFileMode(QFileDialog::ExistingFile);
	dialog.setViewMode(QFileDialog::Detail);
	dialog.setAcceptMode(QFileDialog::AcceptOpen);
	
	// Execute
	QString fileName;
	 if (dialog.exec()) 
	 	fileName = dialog.selectedFiles()[0];
	 else 
	 	return;

	loadSignal(fileName);
	((QWidget *)parent())->parentWidget()->setWindowTitle(fileName);
	
	
}
void PlotScene::save(){
	
	
	
	//File Dialog
	QFileDialog dialog((QWidget *)parent(),tr("Open File(s)"));
	
	// Initial Directory
	QString dir="/home";
	
	#ifdef Q_OS_WIN32 
		dir="C:\\";
	#endif
	
	dialog.setDirectory(dir);

	dialog.setViewMode(QFileDialog::Detail);
	dialog.setAcceptMode(QFileDialog::AcceptSave);
	
	// Execute
	QString fileName;
	if (dialog.exec()){
	 	fileName = dialog.selectedFiles()[0];
 	}
	else
		return;
	 
	//signal.save(fileName.toStdString().c_str());
	//((QWidget *)parent())->parentWidget()->setWindowTitle(fileName);
}

