/**
 * @file ProgressBarQt.cpp
 * @brief Show a Progress-Bar with time estimation
 * @author Michael Koch
 * @date 25/03/2010

 */
#include "core/image/ImageT.h"
#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"
#include <core/imagedisplay/ImageDisplay.h>
#include <core/imagedisplay/QtFramework.h>


#include <iostream>
#ifndef WIN32
#include <sys/time.h>
#endif

#include "vislearning/baselib/ProgressBarQt.h"


using namespace OBJREC;

using namespace std;

using namespace NICE;

ProgressBarQt::ProgressBarQt ( const std::string & _name, bool _useGraphics )
    : useGraphics ( _useGraphics )
{
  name = _name;
  step = 0;

  display_on = false;
  working = true;
  if ( graphicIsAvailable() )
  {
    if ( qApp == NULL )
    {
      QtFramework::instance();
    }

    dialogwindow = new QWidget;

    progressdialog = new QProgressDialog ( "Process at work ...", "Cancel",
                                           0, 100 );
    layout = new QGridLayout ( dialogwindow );
    layout->addWidget ( progressdialog, 0, 0 );
    dialogwindow->setLayout ( layout );
  }
  reset ( _name );
}

ProgressBarQt::~ProgressBarQt()
{
    if( this->dialogwindow != NULL)
    {
        delete this->dialogwindow;
        this->dialogwindow = NULL;
    }
}

void ProgressBarQt::timediff2str(char *text, double dtime)
{
  int time = int (dtime / 60);
	double seconds = dtime - time*60;
	int minutes;
	int hours;

	minutes = time % 60;
	time /= 60;
	hours = time;

	if (hours != 0)
	{
		sprintf(text, "%dh %dm %5.2fs", hours, minutes, seconds);
	}
	else if (minutes != 0)
	{
		sprintf(text, "%dm %5.2fs", minutes, seconds);
	}
	else
	{
		sprintf(text, "%fs", seconds);
	}
}

void ProgressBarQt::displayTimeStat(int posy, char *text, double time)
{
  // Text (char *str,int x0,int y0,int val,int exp,Image img);
  char disptext[200];
  char timetext[200];

  timediff2str ( timetext, time );
  sprintf ( disptext, "%s %s", text, timetext );

}

double ProgressBarQt::getCurrentTime()
{

#ifdef WIN32
	fthrow(Exception,"function not yet ported, use boost::time_date here");
#else
  struct timeval curtime;

  gettimeofday ( &curtime, NULL );

	//return curtime.tv_sec * 100.0 + curtime.tv_usec / 10000.0;
	return curtime.tv_sec + curtime.tv_usec * 1e-6;
#endif
}

void ProgressBarQt::show()
{
  if ( !display_on )
  {
    display_on = true;
  }
  if ( graphicIsAvailable() )
  {
    if ( qApp == NULL )
    {
      QtFramework::instance();
    }
    dialogwindow->show();
  }
}

void ProgressBarQt::hide()
{

	if (display_on)
	{
		display_on = false;
	}
	if (graphicIsAvailable())
	{
		dialogwindow->hide();
	}
}

void ProgressBarQt::stop()
{

  working = false;
}

void ProgressBarQt::reset ( const std::string & _name )
{
  name = _name;
  step = 0;
  elapsed_time = 0;
  avg_time_step = 0;
  start_time = getCurrentTime();
}

void ProgressBarQt::update ( int count )
{
	step++;

	double progress = step / (double) count;

	elapsed_time = getCurrentTime() - start_time;
	avg_time_step = elapsed_time / step;
	estimated_time = (count - step) * avg_time_step;

	size_t mod;
	if (avg_time_step > 1.0)
		mod = 1;
	else
		mod = (size_t) (1.0 / avg_time_step) + 1;

	if ((mod <= 1) || (step % mod == 0))
	{
		char percent_text[10];
		sprintf(percent_text, "%4.2f %%", step * 100.0 / count);

		displayTimeStat(0, "Elapsed Time : ", elapsed_time);
		displayTimeStat(1, "Estimated Time : ", estimated_time);
		displayTimeStat(2, "Avg. Time per step : ", avg_time_step);

		char eltime[200];
		char estime[200];
		char avgtime[200];
		timediff2str(eltime, elapsed_time);
		timediff2str(estime, estimated_time);
		timediff2str(avgtime, avg_time_step);
		fprintf(
				stderr,
				"[PROGRESS] %s %s (elapsed time %s, estimated time %s, avg %s), \n",
				name.c_str(), percent_text, eltime, estime, avgtime);
		//set progress value.
		if (graphicIsAvailable())
		{
			progressdialog->setValue(progress * 100);
		}
	}
}

bool ProgressBarQt::graphicIsAvailable()
{
  return ( useGraphics && ( getenv ( "DISPLAY" ) != NULL ) );
}
