/*****************************************************************************
 *
 *  consoledialog.cpp -- Display console for command line task output.
 * 
 *  Copyright (C) 2010 Starbuck <starbuck@labdv.com>
 *  All rights reserved.
 *
 *  This file is part of the Gui4 module of the DVDx 4 application.
 *
 *  GNU Lesser General Public License Usage
 *  This file may be used under the terms of the GNU Lesser General
 *  Public License version 2.1 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.LGPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU Lesser General Public License version 2.1 requirements
 *  will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 *
 *  GNU General Public License Usage
 *  Alternatively, this file may be used under the terms of the GNU
 *  General Public License version 3.0 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.GPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU General Public License version 3.0 requirements will be
 *  met: http://www.gnu.org/copyleft/gpl.html.
 *
 *****************************************************************************/

#include "consoledialog.h"
#include <QtGui>
#include <QFontMetrics>

ConsoleDialog::ConsoleDialog(const QString &title, const QString &name, const QString &command,
	const QString &engine, const int pid, const bool reverseLayout)
	: task(0), totalTime(0.0)
{
	int charWidth;

	setWindowFlags(Qt::CustomizeWindowHint);  // Turns off the default window title hints.
	setWindowFlags(Qt::WindowTitleHint);      // Gives the window a title bar.

	this->title = title.isEmpty() ? tr("Console") : title;
	setWindowTitle( this->title );

	this->name = name;
	this->engine = engine;
	this->command = command;
	this->pid = pid;

	progress = new QProgressBar();
	progress->setRange(0,100);

	stdOut = new QTextEdit();
	stdErr = new QTextEdit();

	stdOut->setLineWrapMode( QTextEdit::NoWrap );
	stdErr->setLineWrapMode( QTextEdit::NoWrap );

	taskTitle = new QLabel (  tr("%1").arg(this->name) );
	
	if ( pid != 0 )
	{
		taskTitle->setToolTip( tr("%1 running with PID %2").arg(engine).arg(pid) );
	}
	else
	{
		taskTitle->setToolTip( tr("Waiting") );
	}

	taskTitle->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
	
	int stdOutCharHeight = stdOut->fontMetrics().height();
	int stdErrCharHeight = stdErr->fontMetrics().height();
	stdOut->setMaximumHeight( 35 * stdOutCharHeight );
	stdErr->setMaximumHeight( 8 * stdErrCharHeight );
	stdOut->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
	stdErr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
	stdOut->setReadOnly(true);
	stdErr->setReadOnly(true);

	dashBoardWidget = new QWidget;
	dashBoardLayout = new QHBoxLayout(dashBoardWidget);
	dashBoardLayout->setContentsMargins(0,0,0,0);

	dashBoardLayout->addWidget(taskTitle);
	dashBoardLayout->addWidget(progress);

	QVBoxLayout *mainLayout = new QVBoxLayout();

	QGroupBox *cmdGroup = new QGroupBox( tr("Command") );
	QHBoxLayout *cmdLayout = new QHBoxLayout(cmdGroup);
	cmdLine = new QLabel(command, cmdGroup);
	cmdLine->setWordWrap(true);
	cmdLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
	cmdLayout->addWidget(cmdLine);

	QLabel *stdOutLabel = new QLabel ( tr("Standard output:") );
	QLabel *stdErrLabel = new QLabel ( tr("Error output:") );

	if ( reverseLayout )
	{
		stdErrLabel->setText( tr("Information channel:") );
		stdErrLabel->setToolTip( tr("Messages from error ouput") );
		stdErr->setMaximumHeight( 33 * stdOutCharHeight );
		stdOut->setMaximumHeight( 6 * stdErrCharHeight );
		mainLayout->addWidget(dashBoardWidget);
		mainLayout->addWidget(cmdGroup);
		mainLayout->addWidget(stdErrLabel);
		mainLayout->addWidget(stdErr);
		mainLayout->addWidget(stdOutLabel);
		mainLayout->addWidget(stdOut);
	}
	else
	{
		stdOut->setMaximumHeight( 33 * stdOutCharHeight );
		stdErr->setMaximumHeight( 6 * stdErrCharHeight );
		mainLayout->addWidget(dashBoardWidget);
		mainLayout->addWidget(cmdGroup);
		mainLayout->addWidget(stdOutLabel);
		mainLayout->addWidget(stdOut);
		mainLayout->addWidget(stdErrLabel);
		mainLayout->addWidget(stdErr);
	}

	charWidth = stdOut->fontMetrics().averageCharWidth();
#ifdef WIN32
	setMinimumWidth( charWidth * 100 );
#else
	setMinimumWidth( charWidth * 60 );
#endif
	setLayout(mainLayout);
}

void ConsoleDialog::reject()
{
	// Don't close, just hide
	hide();
}

void ConsoleDialog::displayProgress(int *frame, double *time, int *percent, int *size)
{
	changeStateDisplay();

	if ( (*frame > 0 || *size > 0) && *percent == -1 && totalSize > 0 ) 
	{
		double sizePercent = double(*size) / double(totalSize) * 100.0 + 1.0; // round >99.0 to 100
		*percent = (int)sizePercent;
		if (*percent > 100) *percent = 100;
		progress->setValue( *percent );
	}
	else if ( *frame > 0 && totalFrame > 0 ) 
	{
		double framePercent = double(*frame) / double(totalFrame) * 100.0 + 1.0; // round >99.0 to 100
		*percent = (int)framePercent;
		if (*percent > 100) *percent = 100;
		progress->setValue( *percent );
	}
	else if ( (*frame > 0 || *size > 0) && *percent == -1 && totalTime > 0.0 && *time > 0.0 ) 
	{
		double timePercent = (*time) / totalTime * 100.0 + 1.0; // round >99.0 to 100
		*percent = (int)timePercent;
		if (*percent > 100) *percent = 100;
		progress->setValue( *percent );
	}
	else if (*percent > -1)
	{
		progress->setValue(*percent);
	}
	
	emit progressUpdated( *frame, *time, *percent, *size );
}

void ConsoleDialog::displayProgress()
{
	changeStateDisplay();
	
	emit progressUpdated();
}

void ConsoleDialog::changeStateDisplay()
{
	Task::State state = task->getState();
	int pid = task->getPidNumber();

	switch (state)
	{
	case Task::Running:
		if (pid) taskTitle->setToolTip( tr("%1 running with PID %2").arg(engine).arg(pid) );
		progress->setDisabled(false);
		break;
	case Task::Terminated:
		taskTitle->setToolTip( tr("%1 process terminated").arg(engine) );
		progress->setDisabled(true);
		break;
	case Task::Done:
		taskTitle->setToolTip( tr("%1 process completed").arg(engine) );
		progress->setDisabled(true);
		break;
	case Task::Aborted:
		taskTitle->setToolTip( tr("%1 process aborted").arg(engine) );
		progress->setDisabled(true);
		break;
	}
}

void ConsoleDialog::displayOutput(QString *text)
{
	if ( !text->isEmpty() ) stdOut->append( *text );
}

void ConsoleDialog::displayError(QString *text)
{
	if ( !text->isEmpty() ) stdErr->append( *text );
}

void ConsoleDialog::attachTask(Task *t)
{
	task = t; 

	connect( task, SIGNAL(stateChanged()), this, SLOT(displayProgress()) );
}
