//
// C++ Implementation: BodyMeasurementsMainWidget
//
// Description: 
//
//
// Author: Muylkens Toon <toon.muylkens@student.kuleuven.be>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "BodyMeasurementsMainWidget.h"
//    #include <stdio.h>
//    #include <iostream>
//    using namespace std;

/**
*Constructs a new BodyMeasurementsMainWidget
*@param filehandler: A legal filehandler with a legal profile loaded into it
*@param parent: parent widget
*@param leftList: QListWidget used for browsing this BodyMeasurementsMainWidget
*@param toolBar: QToolBar used to place icons for common actions used by this BodyMeasurementsMainWidget
*/
BodyMeasurementsMainWidget::BodyMeasurementsMainWidget(ConfigFileHandlerBodyMeasurements *filehandler, QWidget *parent, QListWidget *leftList, QToolBar *toolBar)
     : QWidget(parent)
{
	ui.setupUi(this);
	this->filehandlerBodyMeasurements = filehandler;
	active=false;
	this->leftList = leftList;
	this->toolBar = toolBar;

	///Gui stuff:
	groupBox_2 = new QGroupBox(ui.page);	///the information group box
    	gridLayout = new QGridLayout(groupBox_2);
    	gridLayout->setHorizontalSpacing(6);
    	gridLayout->setVerticalSpacing(6);
    	gridLayout->setContentsMargins(9, 9, 9, 9);
    	ui.vboxLayout1->addWidget(groupBox_2);
    	QSpacerItem *spacerItem2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
	ui.vboxLayout1->addItem(spacerItem2);
	groupBox_2->setTitle(QApplication::translate("MainWidget", "Information", 0, QApplication::UnicodeUTF8));

	makeActions();
}



/**
*this method constructs all the actions needed by this Widget
*/
void BodyMeasurementsMainWidget::makeActions(){
   
    actionAdd_Body_Part = new QAction(this);
    actionAdd_Body_Part->setObjectName(QString::fromUtf8("actionAdd_Body_Part"));
    actionAdd_Body_Part->setIcon(QIcon(QString::fromUtf8(":/planner/filenew.png")));
    actionAdd_Body_Part->setText(QApplication::translate("MainWindow", "Add BodyPart", 0, QApplication::UnicodeUTF8));
}

/**
*This method makes all the QListWidgetItems that are needed when this widget is active
*/
void BodyMeasurementsMainWidget::makeQListWidgetItems(){
	leftList->clear();
	const QSize size = QSize(32,32);
	leftList->setIconSize(size);
	leftList->setSpacing(5);
	InformationItem = new QListWidgetItem(tr("Information"),leftList);
	InformationItem->setIcon(QIcon(":/left/information.png"));
	AddBodyDataItem = new QListWidgetItem(tr("Add Data-Points"),leftList);
	AddBodyDataItem->setIcon(QIcon(":/left/datapoints.png"));
	PlotBodyPartDataItem = new QListWidgetItem(tr("Plots"),leftList);
	PlotBodyPartDataItem->setIcon(QIcon(":/left/plots.png"));
	ViewAndManageBodyPartsItem = new QListWidgetItem(tr("Body Parts"),leftList);
	ViewAndManageBodyPartsItem->setIcon(QIcon(":/left/exercises.png"));
}

/**
*This method return pointers of all the InformationItems needed when this widget is active
*They are oreded by index! 0->list.size()-1
*/
QList<QListWidgetItem*> BodyMeasurementsMainWidget::getQListWidgetItem(){
	QList<QListWidgetItem*> list;
	list.append(InformationItem);
	list.append(AddBodyDataItem);
	list.append(PlotBodyPartDataItem);
	list.append(ViewAndManageBodyPartsItem);
	return list;
}


/**
*Slot: an item on the leftList has been clicked
*/
void BodyMeasurementsMainWidget::itemhasbeenchanged(QListWidgetItem *current)
{
if(active){
 	if(InformationItem->isSelected()){
 		setCurrentIndex(0);
 		setToolBar(0);
 		}
 
 	if(AddBodyDataItem->isSelected()){
 		setCurrentIndex(1);
 		setToolBar(1);
 		}
	if(ViewAndManageBodyPartsItem->isSelected()){
 		setCurrentIndex(3);
 		setToolBar(3);
 		}
	if(PlotBodyPartDataItem->isSelected()){
 		setCurrentIndex(2);
 		setToolBar(2);
 		}

}
}




/**
*Depending on which module is selected, other icons must be shown.
*stackIndex corresponds to the selected widget in the stackWidget
*/
void BodyMeasurementsMainWidget::setToolBar(int stackIndex){

emit updateToolBar();

	if(stackIndex==3){
	toolBar->addSeparator();
	toolBar->addAction(actionAdd_Body_Part);
	}
	
}


/**
*The index of the stacked widget is set to 'index'
*/
void BodyMeasurementsMainWidget::setCurrentIndex(int index){
ui.stackedWidget->setCurrentIndex(index);
if(index==2){
plotBodyPartData->rescale(); ///still needs to be executed because Qt seems to only automaticly resize the widget when it is NOT hidden.
	}
if(index==3){
viewAndManageBodyParts->rescale(); ///still needs to be executed because Qt seems to only automaticly resize the widget when it is NOT hidden.
	}
}

/**
*Prepare for log-out gui status
*/
void BodyMeasurementsMainWidget::logout(){
setCurrentIndex(0);
active=false;
leftList->clear();
}

/**
*Prepare for log-in gui status and update subWidgets
*/
void BodyMeasurementsMainWidget::login(){
active=true;
addDataWidget->loadsettings(filehandlerBodyMeasurements);
viewAndManageBodyParts->loadsettings(filehandlerBodyMeasurements);

makeQListWidgetItems();
updateInformation();
}

/**
*Execute this method when openingen a new BodyMeasurements profile.
*It loads all the neccesary widgets into the stackWidget
*/
void BodyMeasurementsMainWidget::loadsettings(ConfigFileHandlerBodyMeasurements *filehandlerBodyMeasurements){

	this->filehandlerBodyMeasurements = filehandlerBodyMeasurements;
	addDataWidget = new AddBodyData(ui.stackedWidget);
	viewAndManageBodyParts = new ViewAndManageBodyParts(ui.stackedWidget);	
	plotBodyPartData = new QtrainerPlotWidget(ui.stackedWidget);

	plotBodyPartData->setText(tr("       *On the Y-axis you see the values you entered\n"
"       *On the X-axis you see the number of days from today.\n"
"You can choose how many Datapoints to use for the plotting. Maybe you don't want to plot really old data.  If less than two Datapoints are available, no plot is available."));
	plotBodyPartData->show();
	
	fillPlotWidget();

	

// 		QVector<QPointF> vector = filehandlerBodyMeasurements->getBmi()->getVector();
// 		int number = vector.size();
// 		bool bezier = true;
// 		bool spline = false;
// 		bool line = false;

		/*int number = filehandlerBodyMeasurements->getBmi()->getNbPointsToPlot();
		bool bezier = filehandlerBodyMeasurements->getBmi()->getBezier();
		bool line = filehandlerBodyMeasurements->getBmi()->getLine();
		bool spline = filehandlerBodyMeasurements->getBmi()->getSpline();
		*/
// plotBodyPartData->addDataSet(vector,number, tr("Bmi"), bezier, line, spline);
	
	

	scrollareaplot = new QScrollArea(ui.stackedWidget);
	scrollareaplot->setFrameShape(QFrame::NoFrame);
	scrollareaplot->setFrameShadow(QFrame::Plain);
	scrollareaplot->setWidget(plotBodyPartData);

	ui.stackedWidget->insertWidget(1,addDataWidget);
	addDataWidget->setMinimumSize(QSize(300,300));

	ui.stackedWidget->insertWidget(2,scrollareaplot);
	plotBodyPartData->setMinimumSize(QSize(300,300));

	ui.stackedWidget->insertWidget(3,viewAndManageBodyParts);
	viewAndManageBodyParts->setMinimumSize(QSize(300,300));


	setconnections();
}

/**
*Sets all the neccesary connections
*/
void BodyMeasurementsMainWidget::setconnections()
{
	QObject::connect(addDataWidget,SIGNAL(dataPointAdded(int)),this,SLOT(updateVisualisation(int)));
	QObject::connect(filehandlerBodyMeasurements,SIGNAL(bodyPartChanged(int)),this, SLOT(updateVisualisation(int)));
	QObject::connect(filehandlerBodyMeasurements,SIGNAL(bodyPartChanged()),addDataWidget, SLOT(reloadWidgets()));

	QObject::connect(filehandlerBodyMeasurements,SIGNAL(bodyPartIndexingChanged()),addDataWidget, SLOT(reloadWidgets()));
	
	QObject::connect(filehandlerBodyMeasurements,SIGNAL(bodyPartIndexingChanged()),this, SLOT(updateVisualisation()));

	QObject::connect(actionAdd_Body_Part,SIGNAL(triggered()),this,SLOT(addBodyPart()));
	QObject::connect(this, SIGNAL(bodyPartWasAdded()), viewAndManageBodyParts, SLOT(drawWidgets()));
	QObject::connect(this, SIGNAL(bodyPartWasAdded()), addDataWidget, SLOT(reloadWidgets()));

	QObject::connect(plotBodyPartData,SIGNAL(savePlotMethodInProfile(QStringList,int)),this,SLOT(storePlotMethod(QStringList, int)));	
	QObject::connect(plotBodyPartData,SIGNAL(saveNbOfPointsToPlotInProfile(int,int)),this,SLOT(storeNbPointsToPlot(int,int)));

	
}

/**
*SLOT: Add a BodyPart by calling the AddBodyPart widget
*/
void BodyMeasurementsMainWidget::addBodyPart(){
	AddBodyPart *widget = new AddBodyPart(0);
	widget->setWindowFlags(Qt::SubWindow); 
	widget->show();
	QObject::connect(widget, SIGNAL(addBodyPartToProfile(QString,QString,QString)),this,SLOT( addBodyPartToProfile(QString,QString,QString)));
}

/**
*SLOT: add a BodyPart with given name, unit, explanation to the Profile!
*/
void BodyMeasurementsMainWidget::addBodyPartToProfile(QString name,QString unit,QString exp){
	int index = filehandlerBodyMeasurements->getMeasurables().size();
	BodyPart *part = new BodyPart(unit, name, index);
	part->setExplanation(exp);
	filehandlerBodyMeasurements->addBodyPart(part,true);
	emit bodyPartWasAdded();
}

/**
*SLOT: Lets the sub-widgets adjust to the new size
*/
void BodyMeasurementsMainWidget::rescale(){
viewAndManageBodyParts->rescale();
plotBodyPartData->rescale();
}

/**
*reimplementation of resizeEvent to make subwidgets resize correctly
*/
void BodyMeasurementsMainWidget::resizeEvent(QResizeEvent * event) {
QWidget::resizeEvent(event);
rescale();
}


/**
*SLOT: save the plotmethods into the profile
*/
void BodyMeasurementsMainWidget::storePlotMethod(QStringList list, int index){
filehandlerBodyMeasurements->getMeasurables().at(index)->setPlotMethod(list);
filehandlerBodyMeasurements->savedata();
}

/**
*SLOT: save the nb of points to use for plotting into the profile
*/
void BodyMeasurementsMainWidget::storeNbPointsToPlot(int number,int index){
filehandlerBodyMeasurements->getMeasurables().at(index)->setNbOfPointsToPlot(number);
filehandlerBodyMeasurements->savedata();
}


/**
*Update all the visual representations of the bodypart with index 'index'.
*This means updating the plots, information dialogs, ...
*/
void BodyMeasurementsMainWidget::updateVisualisation(int index){
QVector<QPointF> vector = filehandlerBodyMeasurements->getBodyParts().at(index)->getVector();
int number = filehandlerBodyMeasurements->getBodyParts().at(index)->getNbOfPointsToPlot();
plotBodyPartData->updateDataSet(vector,number,filehandlerBodyMeasurements->getBodyParts().at(index)->objectName(), index);


///replot bmi
Bmi *bmi = filehandlerBodyMeasurements->getBmi();
vector = bmi->getVector();
number = bmi->getNbOfPointsToPlot();
//TODO: nbPointstoPlot may need to be increased, but not always. detect when and increase it.
plotBodyPartData->updateDataSet(vector,number,bmi->getName(), bmi->getIndex());

updateInformation();
}

/**
*Clears and fills the QtrainerPlotWidget with information from the profile
*/
void BodyMeasurementsMainWidget::fillPlotWidget(){
plotBodyPartData->clear();
	QList<Measurable*> list = filehandlerBodyMeasurements->getMeasurables();
	int size1 = list.size();
	for (int i=0;i<size1; i++){
		QVector<QPointF> vector;
		if(list.at(i)->isBodyPart()){
			vector = ((BodyPart*)list.at(i))->getVector();
			}
		if(list.at(i)->isBmi()){
			vector = ((Bmi*)list.at(i))->getVector();
			filehandlerBodyMeasurements->getBmi()->setIndex(i);
			}		
		int number = list.at(i)->getNbOfPointsToPlot();
		bool bezier = list.at(i)->getBezier();
		bool line = list.at(i)->getLine();
		bool spline = list.at(i)->getSpline();
		QString name = list.at(i)->getName();
		plotBodyPartData->addDataSet(vector,number,name , bezier, line, spline);
	}

}

/**
*Update all the visual representations of the bodyparts
*This means updating the plots, information dialogs, ...
*/
void BodyMeasurementsMainWidget::updateVisualisation(){
int size1 = filehandlerBodyMeasurements->getBodyParts().size();
if(plotBodyPartData->getNbOfPlotFrames() > size1){
	///a bodypart was deleted
	fillPlotWidget();
}
else{
	///BodyPart added or modified
	for (int i=0;i<size1; i++){
		QVector<QPointF> vector = filehandlerBodyMeasurements->getBodyParts().at(i)->getVector();
		int number = filehandlerBodyMeasurements->getBodyParts().at(i)->getNbOfPointsToPlot();
		/*bool bezier = filehandlerBodyMeasurements->getBodyParts().at(i)->getBezier();
		bool line = filehandlerBodyMeasurements->getBodyParts().at(i)->getLine();
		bool spline = filehandlerBodyMeasurements->getBodyParts().at(i)->getSpline();
		*/
		//plotBodyPartData->addDataSet(vector,number, filehandlerBodyMeasurements->getBodyParts().at(i)->objectName(), bezier, line, spline);
		QString title = filehandlerBodyMeasurements->getBodyParts().at(i)->getName();
		plotBodyPartData->updateDataSet(vector, number, title, i);
	}
}
///replot bmi
Bmi *bmi = filehandlerBodyMeasurements->getBmi();
QVector<QPointF> vector = bmi->getVector();
int number = bmi->getNbOfPointsToPlot();
//TODO: nbPointstoPlot may need to be increased, but not always. detect when and increase it.
plotBodyPartData->updateDataSet(vector,number,bmi->getName(), bmi->getIndex());

updateInformation();
}

/**
* This method updates the InformationItem's Widget. It displays the progress ...
*/
void BodyMeasurementsMainWidget::updateInformation()
{
for(int i=0; i<informationlabels.size();i++){
	informationlabels.at(i)->close();
	}
informationlabels.clear();

QString text=tr("ProfileName: ");
text.append(filehandlerBodyMeasurements->getprofilename());
text.append(" (");
text.append(filehandlerBodyMeasurements->getSport());
text.append(")");
QLabel *profileLabel = new QLabel(text,groupBox_2);
gridLayout->addWidget(profileLabel, 0, 0, 1, 1);

QLabel *label = new QLabel(tr("<B>Most recent measurements</B>\n:"),groupBox_2);
gridLayout->addWidget(label, 1, 0, 1, 1);
informationlabels.append(label);

int size = filehandlerBodyMeasurements->getBodyParts().size();
int index = 2;
for(int i=0; i<size; i++){
	BodyPart *part = filehandlerBodyMeasurements->getBodyParts().at(i);
	if(part->hasMeasurement(part->getDateLatestMeasurement() )) {
		QString text = part->objectName();
		text.append(": ");
		QString num;
		num.setNum(part->getMeasurement(part->getDateLatestMeasurement() )->getValue());
		text.append(num);
		text.append(part->unitName());	
		QLabel *label = new QLabel(text,groupBox_2);
		gridLayout->addWidget(label, index, 0, 1, 1);
		informationlabels.append(label);
		index++;
		}
	}

}

