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

///VIEWANDMANAGESCHEDULE

ViewAndManageSchedule::ViewAndManageSchedule(QWidget *parent, ConfigFileHandlerPowerTraining *filehandler)
     : QWidget(parent)
{

     	ui.setupUi(this);
	this->filehandler=filehandler;
	oneScheduleList = QList<OneSchedule*>();

	displayer = new TrainScheduleDisplayer(0);
	displayer->hide();
	displayer->setWindowFlags(Qt::SubWindow);

}

void ViewAndManageSchedule::loadsettings(ConfigFileHandlerPowerTraining *filehandler){
this->filehandler=filehandler;
reloadScheduleList();
}

/**
*Public SLOT: Opens widget to make a new Schedule
*/
void ViewAndManageSchedule::addSchedule(){
TrainingScheduleDesigner *widget = new TrainingScheduleDesigner(0,filehandler);
widget->setWindowFlags(Qt::SubWindow);
widget->show();
QObject::connect(widget,SIGNAL(reloadScheduleList()),this, SLOT(reloadScheduleList()));
}

/**
*Public SLOT: Reloads all the schedules in the list.
*/
void ViewAndManageSchedule::reloadScheduleList(){
for (int i=0;i<oneScheduleList.size();i++){
oneScheduleList.at(i)->close();
}
oneScheduleList.clear();
QList<TrainingSchedule*> myList = QList<TrainingSchedule*>(filehandler->getTrainingSchedules());
for(int i=0;i<myList.size();i++){
	OneSchedule *widget = new OneSchedule(this);
	widget->setName(myList.at(i)->getName());
	widget->setExplanation(myList.at(i)->getExplaination());
	ui.vboxLayout->insertWidget(2,widget);
	widget->show();
	oneScheduleList.append(widget);
	QObject::connect(widget, SIGNAL(showSchedule(QString)),this, SLOT(showSchedule(QString)));
	QObject::connect(widget, SIGNAL(editSchedule(QString)),this, SLOT(editSchedule(QString)));
	QObject::connect(widget, SIGNAL(deleteSchedule(QString,OneSchedule*)),this, SLOT(deleteSchedule(QString,OneSchedule*)));
	}
rescale();
}

/**
*SLOT: starts the Exercise selecter, which in his turn starts the displayer
*/
void ViewAndManageSchedule::showSchedule(QString name){
selectExerciseWidget = new SelectExerciseWidget(0,name,filehandler);
selectExerciseWidget->setWindowFlags(Qt::SubWindow);
QObject::connect(selectExerciseWidget, SIGNAL(showSchedule(QList<QString>,QString)),this, SLOT(showSchedule(QList<QString>,QString)));
selectExerciseWidget->show();
}

/**
*SLOT: edit schedule: opens the TrainingScheduleDesigner
*/
void ViewAndManageSchedule::editSchedule(QString name){

bool schedulefound=false; //if we don't find a schedule with the given name...
TrainingSchedule *schedule = new TrainingSchedule();
QList<TrainingSchedule*> list = filehandler->getTrainingSchedules();
for(int i=0;i<list.size() && !schedulefound;i++){
///linear search. Find the schedule with the given name
if(list.at(i)->getName()==name){
	schedule=list.at(i);
	schedulefound=true;
	}
}
if(schedulefound){
	TrainingScheduleDesigner *widget = new TrainingScheduleDesigner(0,filehandler);
	widget->setWindowFlags(Qt::SubWindow);
	widget->setSchedule(schedule);
	widget->show();
	QObject::connect(widget,SIGNAL(reloadScheduleList()),this, SLOT(reloadScheduleList()));
	QObject::connect(widget,SIGNAL(changed(QString, TrainingSchedule*)),filehandler, SLOT(someTrainingScheduleChanged(QString, TrainingSchedule*)));
	QObject::connect(widget,SIGNAL(changed(QString, TrainingSchedule*)),this, SLOT(someTrainingScheduleChanged(QString, TrainingSchedule*)));
	}
}

/**
*this slot is meant to inform the grid widget that it needs to update its 'other scheduleOccurrences'
*/
void ViewAndManageSchedule::someTrainingScheduleChanged(QString oldName, TrainingSchedule *newschedule){
emit reloadScheduleNames();
}




/**
*SLOT: starts the ScheduleDisplayer
*/
void ViewAndManageSchedule::showSchedule(QList<QString> allowedExercisesList, QString name){
selectExerciseWidget->close();
displayer->setSchedule(name,filehandler,allowedExercisesList);
displayer->show();
}


/**
*SLOT: 
*/
void ViewAndManageSchedule::deleteSchedule(QString name, OneSchedule *widget){
widget->close();
filehandler->deleteTrainingSchedule(name);
}


/**
* set the width, necessery because of the QScrollArea, slot
* Needs to be executed after selecting this widget from the left-bar
*/
void ViewAndManageSchedule::rescale()
{
this->resize(parentWidget()->size().width()-10,filehandler->getTrainingSchedules().size()*200);
}



///ONESCHEDULE


OneSchedule::OneSchedule(QWidget *parent)
     : QWidget(parent)
{
     	ui.setupUi(this);
	QObject::connect(ui.showButton,SIGNAL(pressed()),this,SLOT(showSchedule()));
	QObject::connect(ui.deleteButton,SIGNAL(pressed()),this,SLOT(deleteSchedule()));
	QObject::connect(ui.editButton,SIGNAL(pressed()),this,SLOT(editSchedule()));
}

void OneSchedule::showSchedule(){
emit showSchedule(ui.groupBox->title()); ///emits signal with schedulename as parameter
}

void OneSchedule::editSchedule(){
emit editSchedule(ui.groupBox->title()); ///emits signal with schedulename as parameter
}

void OneSchedule::deleteSchedule(){
emit deleteSchedule(ui.groupBox->title(),this); ///emits signal with schedulename as parameter
}

/**
*Sets the explanation of the OneExcersise to newexp.
*Only GUI is effected
*/
void OneSchedule::setExplanation(QString newexp){
ui.explanationLabel->setText(newexp);
}

/**
*Sets the name of the OneExcersise to newname.
*Only GUI is effected
*/
void OneSchedule::setName(QString newname){
ui.groupBox->setTitle(newname);
}

///TRAININGSCHEDULEDESIGNER


TrainingScheduleDesigner::TrainingScheduleDesigner(QWidget *parent, ConfigFileHandlerPowerTraining *filehandler)
     : QWidget(parent)
{
     	ui.setupUi(this);
	this->filehandler=filehandler;
	schedule = new TrainingSchedule();
	QObject::connect(ui.addRotationButton,SIGNAL(pressed()),this, SLOT(addRotation()));
	QObject::connect(ui.addIterationButton,SIGNAL(pressed()),this, SLOT(addIteration()));
	QObject::connect(ui.rotationsListWidget,SIGNAL(currentRowChanged(int)),this,SLOT(currentSelectedRotationChanged(int)));
	QObject::connect(ui.iterationsListWidget,SIGNAL(currentRowChanged(int)),this,SLOT(currentSelectedIterationChanged(int)));
	QObject::connect(ui.performanceSpinBox,SIGNAL(valueChanged(int)),this, SLOT(performanceChanged(int)));
	QObject::connect(ui.repetitionsSpinBox,SIGNAL(valueChanged(int)),this, SLOT(repetitionsChanged(int)));
	QObject::connect(ui.addButton,SIGNAL(pressed()),this,SLOT(returnSchedule()));
	editMode=false;
}


/**
*Sets the schedule to 'schedule' and make GUI represent that schedule
*widget goes to editing mode instead of new schedule mode
*/
void TrainingScheduleDesigner::setSchedule(TrainingSchedule *schedule){

	oldName=schedule->getName();

	ui.addButton->setText(tr("Save"));
	this->schedule=schedule;

	ui.nameLineEdit->setText(schedule->getName());
	ui.explanationTextEdit->setText(schedule->getExplaination());

	for(int i=0;i<schedule->getNumberOfRotations();i++){
	QString label=tr("Set ");
	QString str;
	str.setNum(ui.rotationsListWidget->count()+1);
	label.append(str);
	ui.rotationsListWidget->addItem(label);
// 		for(int j=0;j<schedule->getNumberOfTimesExerciseIsRepeatedInARotation(i);j++){
// 			QString label=tr("Iteration ");
// 			QString str;
// 			str.setNum(ui.iterationsListWidget->count()+1);
// 			label.append(str);
// 			ui.iterationsListWidget->addItem(label);
// 			}
	}

	if(ui.rotationsListWidget->count()>0){
		ui.rotationsListWidget->setCurrentRow(0);
		currentSelectedRotationChanged(0);
		if(ui.iterationsListWidget->count()>0){
			ui.iterationsListWidget->setCurrentRow(0);
			currentSelectedIterationChanged(0);
			}
		}
	else{
		ui.rotationsListWidget->clear();
		ui.iterationsListWidget->clear();
		ui.performanceSpinBox->setValue(0);
		ui.repetitionsSpinBox->setValue(0);
	}

	editMode=true;
}

/**
*@return the name of the schedule
*/
QString TrainingScheduleDesigner::getName(){
return ui.nameLineEdit->text();
}

/**
*@return the short explanation of the schedule
*/
QString TrainingScheduleDesigner::getExplanation(){
QString explanation = ui.explanationTextEdit->toPlainText(); 
explanation.replace(QString("\n"), "  ");
return explanation;
}

/**
*@return the short explanation of the schedule
*/
TrainingSchedule TrainingScheduleDesigner::getTrainingSchedule(){
TrainingSchedule schedule = TrainingSchedule(getName(),getExplanation());
int nbRotations = ui.rotationsListWidget->count();
schedule.setNumberOfRotations(nbRotations);
for(int i=0;i<nbRotations;i++){
	///for every rotation, enter # of Iterations/Repetitions
	
}

//schedule.setPerformance(ui.performanceSpinBox->value());
//schedule.setNumberOfTimesExerciseIsDone(

return schedule;
}

/**
*Adds a rotation to the Rotation list and to the Training schedule
*/
void TrainingScheduleDesigner::addRotation(){
	schedule->addRotation();
	QString label=tr("Set ");
	QString str;
	str.setNum(ui.rotationsListWidget->count()+1);
	label.append(str);
	ui.rotationsListWidget->addItem(label);
	ui.rotationsListWidget->setCurrentRow(schedule->getNumberOfRotations()-1);
}

/**
*Adds an Iteration to the selected Rotation in the list AND in the schedule.
*/
void TrainingScheduleDesigner::addIteration(){
	int currentRotation = ui.rotationsListWidget->currentRow();
	if(currentRotation!=-1){
	schedule->addRepetition(currentRotation);
	QString label=tr("Iteration ");
	QString str;
	str.setNum(ui.iterationsListWidget->count()+1);
	label.append(str);
	ui.iterationsListWidget->addItem(label);

	ui.iterationsListWidget->setCurrentRow(schedule->getNumberOfTimesExerciseIsRepeatedInARotation(currentRotation)-1);
	}
}


/**
*Updates the Iteration list and settings to the new status of the schedule.
*@effect sets the Iteratons of the selected Rotation in the IterationList 
*\note it only updates the GUI, not the underliing schedule
*/
void TrainingScheduleDesigner::currentSelectedRotationChanged(int currentRow){
	ui.iterationsListWidget->clear();
	int nbIterations = schedule->getNumberOfTimesExerciseIsRepeatedInARotation(currentRow);
	for(int i=0;i<nbIterations;i++){
	QString label=tr("Iteration ");
	QString str;
	str.setNum(i+1);
	label.append(str);
	ui.iterationsListWidget->addItem(label);
	}
	ui.iterationsListWidget->setCurrentRow(0);
	
}

/**
*Sets Performance and Repetitions of selected Iteration
*\note it only updates the GUI, not the underliing schedule
*/
void TrainingScheduleDesigner::currentSelectedIterationChanged(int currentIteration){
	int currentRotation = ui.rotationsListWidget->currentRow();
	if(currentRotation!=-1 && currentIteration!=-1){
	ui.performanceSpinBox->setValue(schedule->getPerformance(currentRotation,currentIteration));
	ui.repetitionsSpinBox->setValue(schedule->getNumberOfTimesExerciseIsDone(currentRotation,currentIteration));	
	}
}

/**
*This method sets the performance of the selected Rotation and Iteration to the new value. Not in the GUI
*but in the schedule
*/
void TrainingScheduleDesigner::performanceChanged(int newvalue){
int rotation = ui.rotationsListWidget->currentRow();
int iteration = ui.iterationsListWidget->currentRow();
if(rotation!=-1 && iteration!=-1){
	schedule->setPerformance(rotation,iteration,newvalue);
	}
}

/**
*This method sets the #repetitions of the selected Rotation and Iteration to the new value. Not in the GUI
*but in the schedule
*/
void TrainingScheduleDesigner::repetitionsChanged(int newvalue){
int rotation = ui.rotationsListWidget->currentRow();
int iteration = ui.iterationsListWidget->currentRow();
if(rotation!=-1 && iteration!=-1){
	schedule->setNumberOfTimesExerciseIsDone(rotation,iteration,newvalue);
	}
}

/**
*SLOT: called when user pressed 'add schedule' button
*the name, and explanation are put into the schedule
*shows message when name is not a good one.
*saves the schedule into the ConfigFileHandler
*/
void TrainingScheduleDesigner::returnSchedule(){
QString name = getName();
QString explanation = getExplanation();
bool nameOK = StringCheck::check(name,false,tr("The name you entered has illegal\n characters in it or is empty."));
bool explanationOK = StringCheck::check(explanation,true,tr("The explanation you entered has illegal characters in it."));

if(explanationOK && nameOK){
if(!editMode){
	schedule->setName(name);
	schedule->setExplaination(explanation);
	filehandler->addSchedule(schedule); ///this overrides schedules with the same name ///not neccesarry
	emit reloadScheduleList();	
	close();
	}
else if (editMode) {
	QMessageBox msgBox;
	msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
	QString text = tr("Saving now will delete all Schedule Occurrences (second tab in Grid)\n");
	if(oldName!=schedule->getName()){
		text.append(tr("All Planned Trainings will be converted to the new Name you choose"));
		}
	msgBox.setText(text);
	msgBox.setDetailedText(tr("ScheduleOccurences entered in Qtrainer link to a Schedule. If that schedule is changed, the ScheduleOccurrence can become Illegal. That's why it is deleted. Planned Training linked to a schedule can be converted."));
	switch (msgBox.exec()) 
		{
		case QMessageBox::Yes:
			schedule->setName(name);
			schedule->setExplaination(explanation);
			emit reloadScheduleList();	
			emit changed(oldName, schedule);
			close();
		break;
		case QMessageBox::No:
    			// no was clicked
		break;
		}	
	
}
}

}
