/***************************************************************************
 *   Copyright (C) 2007 by Muylkens Toon   *
 *   toon.muylkens@student.kuleuven.be   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *

 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include "QtrainerPlotWidget.h"
#include <QtGui>
//   #include <stdio.h>
//   #include <iostream>
//   using namespace std;



QtrainerPlotWidget::QtrainerPlotWidget(QWidget *parent)
     : QWidget(parent)
 {
	plotlist =  new	QList<QtrainerPlotFrame*>();
	ui.setupUi(this);
	setupconnectionsanddefaults();

	ui.TextLabel->setWordWrap(true);
	//makeallplotters();
}

/**
*Set the welcomes/information text
*/
void QtrainerPlotWidget::setText(QString text){
	ui.TextLabel->setText(text);
	
}

/**
*add a set of points needed to be visualised
*@param vector: all the points ever wanted to be plotted in the plotframe
*@param numberOfPointsToPlot: the number of points to plot now (-1 => plots all points)
*@param title: title of the GUI box
*/
void QtrainerPlotWidget::addDataSet(QVector<QPointF> vector,int numberOfPointsToPlot, QString title, bool bezier, bool line, bool spline){
	if(numberOfPointsToPlot >= vector.size() || numberOfPointsToPlot == -1){
		numberOfPointsToPlot=vector.size();
	}
	plotlist->append(returnPlotFrame(vector,numberOfPointsToPlot, title, bezier, line, spline));
	int i = plotlist->size()-1;
	QObject::connect(plotlist->at(i),SIGNAL(nbOfPointsPlottedChanged(int, int)),this,SLOT(saveNbOfPlointsToPlot(int,int)));
	QObject::connect(plotlist->at(i),SIGNAL(plotMethodChanged(QStringList, int)),this,SLOT(savePlotMethod(QStringList, int)));
	
	///draw the QtrainerPlotFrame
	ui.gridLayout->addWidget(plotlist->at(i), getRowInGrid(i),getColumnInGrid(i));
	ui.gridLayout->setRowMinimumHeight(getRowInGrid(i),410);
	this->setMinimumHeight(410*(getRowInGrid(i)+1)+100);
	ui.gridLayout->setSizeConstraint(QLayout::SetMaximumSize);
	plotlist->at(i)->show();
}


// void QtrainerPlotWidget::rescale(){
// 
// }

/**
*Update the QtrainerPlotFrame with index 'index'
*It is provided with the new parameters and asked for redraw
*/
void QtrainerPlotWidget::updateDataSet(QVector<QPointF> newvector,int numberOfPointsToPlot, QString title, int index){

	if(getNbOfPlotFrames()>index){
		plotlist->at(index)->setDataAndPlot(newvector);
		plotlist->at(index)->setNbOfPointsToPlot(numberOfPointsToPlot);
		plotlist->at(index)->setTitle(title);
		}
	else{
		addDataSet(newvector,numberOfPointsToPlot,title, true,false, false);
		}
}

/**
*Returns the number of plotFrames in this QtrainerPlotWidget
*/
int QtrainerPlotWidget::getNbOfPlotFrames(){
return plotlist->size();
}

/**
*Returns the rownumber of the QtrainerPlotFrame in the grid. Where it should be placed or where it is.
*/
int QtrainerPlotWidget::getRowInGrid(int index){
///At the moment the default is 2 QtrainerPlotFrames per row.
int ret = (int) index/2;
return ret;
}

/**
*Returns the columnnumber of the QtrainerPlotFrame in the grid. Where it should be placed or where it is.
*/
int QtrainerPlotWidget::getColumnInGrid(int index){
///At the moment the default is 2 QtrainerPlotFrames per row.
int ret = index % 2;
return ret;
}

/**
*add a list of sets of points needed to be visualised
*/
void QtrainerPlotWidget::addDataSets(QList< QVector<QPointF> > vectorlist ){
//TODO
}

/**
*make new QtrainerPlotFrame which is still hidden. The parent is this.
*@param vector: all the points ever wanted to be plotted in the plotframe
*@param number: the number of points to plot now (MUST be >0 and bigger then vector.size())
*@param title: title of the gui box
*@param bezier,line, spline: plotmethods
*/
QtrainerPlotFrame* QtrainerPlotWidget::returnPlotFrame(QVector<QPointF> vector, int number, QString title, bool bezier, bool line, bool spline){
int index = plotlist->size();
QtrainerPlotFrame *frame = new QtrainerPlotFrame(this,index);

frame->setDataAndPlot(vector);
frame->setNbOfPointsToPlot(number);
frame->setTitle(title);

frame->setPlotMethod(bezier,line,spline);
frame->hide();

return frame;
}

/**
 * connects all the objects and sets default values
 */
void QtrainerPlotWidget::setupconnectionsanddefaults()
{
//TODO

}

/**
*Remove all QtrainerPlotFrames.
*/
void QtrainerPlotWidget::clear(){
for(int i=plotlist->size()-1; i>0; i--){
	plotlist->at(i)->close();
	}
for (int i=0;i<ui.gridLayout->rowCount();i++){
	ui.gridLayout->setRowMinimumHeight(i, 0);
	}
plotlist->clear();
this->setMinimumHeight(100);
this->setMaximumHeight(100);
}

/**
*Rescales and or repositions the QtrainerPlotFrames to make full use of the new size of this widget
*/
void QtrainerPlotWidget::rescale(){
if(parentWidget()!=0 && this->isVisible()){
 	int a = parentWidget()->width();
 	this->setMinimumWidth(a);
 	this->setMaximumWidth(a);
 	this->setMinimumHeight(100);
	int height  =  190*getNbOfPlotFrames();
	int even = getNbOfPlotFrames()%2;
	if(even ==1 ) {
		height = height+200;
		}
	height+=100;
	this->setMinimumHeight(height);
 	}
}

/**
 *All QtrainerPlotFrames are removed and redrawed
 */
// void QtrainerPlotWidget::reload()
// {
//TODO
//Is this method needed?
// }

/**
*SLOT: another number of points are used for the plot. We need to save it?
*/
void QtrainerPlotWidget::saveNbOfPlointsToPlot(int newnumber,int index){
emit saveNbOfPointsToPlotInProfile(newnumber,index);
}

/**
*SLOT: another plotmethos is used for the plot. We need to save it?
*/
void QtrainerPlotWidget::savePlotMethod(QStringList methodlist,int index){
emit savePlotMethodInProfile(methodlist, index);
}

/**
*Delete old graphics from the profile
*/
void QtrainerPlotWidget::removeOldPlotsSendXML(QString username, QString passwd){
	QSettings settings("ToonSoft", "Qtrainer");
	settings.beginGroup("ProgramSettings");
	QString url = settings.value("DatabaseURL").toString();
	settings.endGroup();

	QxtXmlRpcClient *myClient = new QxtXmlRpcClient(QUrl(url));

	QObject::connect(myClient, SIGNAL(finished(int,QVariant)),this,SLOT(finished(int,QVariant)));
	QObject::connect(myClient, SIGNAL(fault(int,int,QString)),this,SLOT(fault(int,int,QString)));
	QObject::connect(myClient, SIGNAL(parseError(int,QString)),this,SLOT(parseError(int,QString)));
	QObject::connect(myClient, SIGNAL(networkError(int,QString)),this,SLOT(networkError(int,QString)));
	QList<QVariant> params;
	params<<username<<passwd;
	///params:  username<<passwd
	int i = myClient->call(QString("deleteAllPlots"), params);
}


/**
*Uploads the image of the QtrainerPlotFrame with index='index' to the qtrainer server.
*/
void QtrainerPlotWidget::uploadSendXML(int index, QString username, QString passwd){
		
	QString figureName = plotlist->at(index)->getTitle();

	QPixmap pixmap = QPixmap::grabWidget(plotlist->at(index));
	QByteArray bytes;
	QBuffer buffer(&bytes);
	buffer.open(QIODevice::WriteOnly);
	pixmap.save(&buffer, "JPG");
	
	QSettings settings("ToonSoft", "Qtrainer");
	settings.beginGroup("ProgramSettings");
	QString url = settings.value("DatabaseURL").toString();
	settings.endGroup();

	QxtXmlRpcClient *myClient = new QxtXmlRpcClient(QUrl(url));

	QObject::connect(myClient, SIGNAL(finished(int,QVariant)),this,SLOT(finished(int,QVariant)));
	QObject::connect(myClient, SIGNAL(fault(int,int,QString)),this,SLOT(fault(int,int,QString)));
	QObject::connect(myClient, SIGNAL(parseError(int,QString)),this,SLOT(parseError(int,QString)));
	QObject::connect(myClient, SIGNAL(networkError(int,QString)),this,SLOT(networkError(int,QString)));
	QList<QVariant> params;
	params<<username<<passwd<<figureName<<index<<plotlist->size()<<bytes;
	///params:  username<<passwd<<exerciseName<<numberofexercise<<totalnumberofexercises<<bytes
	int i = myClient->call(QString("storeplot"), params);
}


void QtrainerPlotWidget::parseError(int callId, QString errorMsg){
	QMessageBox msgBox;
	msgBox.setIcon(QMessageBox::Critical);
	msgBox.setStandardButtons(QMessageBox::Ok);
	msgBox.setText(tr("A parse error occured.\nThis is probably Qtrainers fault."));
	msgBox.exec();
}

void QtrainerPlotWidget::networkError(int callId, QString errorMsg){
	QMessageBox msgBox;
	msgBox.setIcon(QMessageBox::Critical);
	msgBox.setStandardButtons(QMessageBox::Ok);
	msgBox.setText(tr("A network error occured."));
	msgBox.exec();
}

void QtrainerPlotWidget::finished(int callId, QVariant retValue){
if(retValue.toString()=="succes"){
	emit succesFullUpload();

}
else{
	emit unsuccesFullUpload();
}

}


void QtrainerPlotWidget::fault(int callId, int faultCode, QString faultString){
	QMessageBox msgBox;
	msgBox.setStandardButtons(QMessageBox::Ok);
	msgBox.setText(tr("Exercise couldn't be uploaded to the online database.\n")+faultString);
	msgBox.exec();
}

/**
*Slot: triggered when all the plots need to be uploaded, it opens a dialog in which the user can enter his username/passwd
*/
void QtrainerPlotWidget::upload(){
LoginRegisterWidget *widget = new LoginRegisterWidget(0);
widget->setprogressBarMax(plotlist->size()-1);
widget->setprogressBarMin(0);
widget->setWindowFlags(Qt::SubWindow);
QObject::connect(widget,SIGNAL(uploadPlots(QString,QString)),this,SLOT(uploadPlots(QString,QString)));
QObject::connect(this,SIGNAL(succesFullUpload()),widget, SLOT(increaseProgressBar()));
QObject::connect(this,SIGNAL(unsuccesFullUpload()),widget, SLOT(showSomethingWrongMessage()));
widget->show();
}

/**
*Slot: triggered after the username is provided
*/
void QtrainerPlotWidget::uploadPlots(QString username, QString passwd){
	removeOldPlotsSendXML(username,passwd);
	for(int i=0;i<plotlist->size();i++){
	uploadSendXML(i,username,passwd);
	}
}



/**
 * returns the number of points to be used to plot the data curve of bench
 * @return  the number of points to be used to plot the data curve of bench
 */
// int QtrainerPlotWidget::getnumberofpointsbench()
// {
// return this->numberofpointsbench;
// }


/**
 * returns the number of points to be used to plot the data curve of biceps
 * @return  the number of points to be used to plot the data curve of biceps
 */
// int QtrainerPlotWidget::getnumberofpointsbiceps()
// {
// return this->numberofpointsbiceps;
// }



