/*      MainForm.cpp
//
//      Copyright 2005-2011 Lucas Tsatiris <systester.project@gmail.com>
//
//      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., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.
//
*/

#include "systester.h"

QFont globalfont, termfont;
QTextEdit *Terminal;
QNetworkAccessManager *UpdateManager;
char termstr[20000] = "", tempstr[256];
bool licpressed = FALSE;
bool stoppressed = FALSE;
QScrollBar *VSBar;

/* constructor */
MainForm::MainForm ()
{
  setupUi (this);
  UpdateManager = new QNetworkAccessManager (this);
  Splash = new SplashWindow;
  Splash->setGeometry (200, 200, 390, 250);
  Splash->hideButtons ();

  connect (runButton, SIGNAL (clicked ()), this, SLOT (runButton_clicked ()));
  connect (modeButton, SIGNAL (clicked ()), this,
	   SLOT (modeButton_clicked ()));
  connect (exitButton, SIGNAL (clicked ()), this,
	   SLOT (exitButton_clicked ()));
  connect (aboutButton, SIGNAL (clicked ()), this,
	   SLOT (aboutButton_clicked ()));
  connect (FontsButton, SIGNAL (clicked ()), this,
	   SLOT (FontsButton_clicked ()));
  connect (flattrButton, SIGNAL (clicked ()), this,
	   SLOT (flattrButton_clicked ()));
  connect (stopButton, SIGNAL (clicked ()), this,
	   SLOT (stopButton_clicked ()));
  connect (threadsBox, SIGNAL (currentIndexChanged (int)), this,
	   SLOT (threadsBox_changed ()));
  connect (updateButton, SIGNAL (clicked ()), this,
	   SLOT (updateButton_clicked ()));
  connect (UpdateManager, SIGNAL (finished (QNetworkReply *)), this,
	   SLOT (updateReplyFinished (QNetworkReply *)));
}

/* destructor */
MainForm::~MainForm ()
{
  delete Splash;
}

/*
 * As it says
 */
void
MainForm::picoremain (int loops, int exec_times, int output_file,
		      int log_file, int threads, int algo)
{
  int i, iterations = 0, executions = 1;

  iterations = loops;
  executions = exec_times;
  pflag = output_file;
  lflag = log_file;

  if (lflag == 1)
    unlink ("systester.log");

  start = pitimer ();

  for (i = 0; i < executions; i++)
    {
      if (stoppressed == TRUE)
	return;

      pass++;

      master (iterations, threads, algo);

      if (i != (executions - 1))
	{
	  strcpy (termstr, "");
	  Terminal->setText (termstr);
	  qApp->processEvents (QEventLoop::AllEvents, 1000);
	}

    }
}

/*
    End of systestercore.cpp
*/

void
MainForm::onload ()
{
  Splash->show ();
  QTimer::singleShot (3000, this, SLOT (initForm ()));
  vsbar = TextTerminal->verticalScrollBar ();
}

void
MainForm::initForm ()
{
  unsigned long long freq;
  int cpu, activecpus;
  char osstring[80], fstring[80], ChipID[64] = "", VendorID[64] = "",
    gmpverstring[12], ilpstring[13];

  cpu = CPUID (ChipID, VendorID);
  activecpus = ncpus ();
  freq = cpufreq ();

  if (cpu == 2)
    CPUPixmap->setPixmap (QPixmap
			  (QString::fromUtf8 (":/images/images/amd.png")));
  else if (cpu == 1)
    CPUPixmap->setPixmap (QPixmap
			  (QString::fromUtf8 (":/images/images/intel.png")));
  else if ((cpu == 3) || (cpu == 4))
    CPUPixmap->setPixmap (QPixmap
			  (QString::fromUtf8 (":/images/images/hp.png")));
  else if (cpu == 0)
    CPUPixmap->setPixmap (QPixmap
			  (QString::fromUtf8 (":/images/images/cpu.png")));

  CPUString->setAlignment (Qt::AlignCenter);
  CPUString->setText (ChipID);
  osid (osstring);
  sprintf (fstring, "Running %s at %ld MHz", osstring, (long) freq);
  FreqString->setText (fstring);
  sprintf (fstring, "NCPUs: %d", activecpus);
  NCPUSString->setText (fstring);
  sprintf (fstring, "%5d MB", (int) (totalmem () / (1024 * 1024)));
  RAMString->setText (fstring);
#if defined (__MPIR_VERSION)
  sprintf (gmpverstring, "GMP %s", GMP_VERSION);
#else
  sprintf (gmpverstring, "GMP %s", gmp_version);
#endif
  GMPVERString->setText (gmpverstring);
  sprintf (ilpstring, " %d bit ", (int) (sizeof (int *) * 8));
  ILPString->setText (ilpstring);

  Terminal = TextTerminal;
  VSBar = vsbar;
  mode = 0;
  Splash->hide ();
  Splash->showButtons ();
  this->show ();
}

void
MainForm::runButton_clicked ()
{

  int loops, executions, log = 0, out = 0, threads;

  Terminal->setVisible (TRUE);
  qApp->processEvents (QEventLoop::AllEvents, 1000);

  stoppressed = FALSE;
  setCursor (Qt::WaitCursor);
  Terminal->setCursor (Qt::WaitCursor);
  stopButton->setCursor (Qt::ArrowCursor);

  digits->setEnabled (FALSE);
  execBox->setEnabled (FALSE);
  threadsBox->setEnabled (FALSE);
  algoBox->setEnabled (FALSE);
  checklog->setEnabled (FALSE);
  checkout->setEnabled (FALSE);
  aboutButton->setEnabled (FALSE);
  exitButton->setEnabled (FALSE);
  flattrButton->setEnabled (FALSE);
  updateButton->setEnabled (FALSE);
  FontsButton->setEnabled (FALSE);
  runButton->setEnabled (FALSE);
  modeButton->setEnabled (FALSE);
  stopButton->setEnabled (TRUE);

  if (licpressed == TRUE)
    Terminal->setFont (globalfont);

  if (algoBox->currentIndex () == 0)
    loops = digits->currentIndex () + 16;
  else
    loops = digits->currentIndex () + 17;


  threads = (int) pow ((double) 2, (double) threadsBox->currentIndex ());
  executions = execBox->currentIndex () + 1;

  if (executions > 10)
    executions = (executions - 10) * 10 + 10;

  if (checklog->isChecked ())
    log = 1;

  if (checkout->isChecked ())
    out = 1;

  Terminal->setAlignment (Qt::AlignLeft | Qt::AlignTop);
  strcpy (termstr, "");
  picoremain (loops, executions, out, log, threads, algoBox->currentIndex ());
  setCursor (Qt::ArrowCursor);
  Terminal->setCursor (Qt::ArrowCursor);

  digits->setEnabled (TRUE);
  execBox->setEnabled (TRUE);
  threadsBox->setEnabled (TRUE);
  algoBox->setEnabled (TRUE);
  checklog->setEnabled (TRUE);
  checkout->setEnabled (TRUE);
  aboutButton->setEnabled (TRUE);
  exitButton->setEnabled (TRUE);
  flattrButton->setEnabled (TRUE);
  updateButton->setEnabled (TRUE);
  FontsButton->setEnabled (TRUE);
  runButton->setEnabled (TRUE);
  if (threadsBox->currentIndex () != 0)
    modeButton->setEnabled (TRUE);
  stopButton->setEnabled (FALSE);
}

void
MainForm::exitButton_clicked ()
{
  qApp->quit ();

}

void
MainForm::modeButton_clicked ()
{
  if (mode == 0)
    {
      mode = 1;
      modeButton->setText (QApplication::translate ("MainWindow", "Bench", 0,
						    QApplication::UnicodeUTF8));
      return;
    }

  mode = 0;
  modeButton->setText (QApplication::translate
		       ("MainWindow", "Test", 0, QApplication::UnicodeUTF8));
  return;

}

void
MainForm::updateButton_clicked ()
{
  updateButton->setText ("Checking");
  UpdateManager->
    get (QNetworkRequest
	 (QUrl ("http://systester.sourceforge.net/lversion.php")));
}

void
MainForm::updateReplyFinished (QNetworkReply * updatereply)
{
  int major, minor, patch;
  int newversion = FALSE, error = TRUE;
  bool majorok, minorok, patchok;

  updateButton->setText ("Update");

  QByteArray replybytes = updatereply->readAll ();
  QString replystring (replybytes);

  QStringList versiondigits =
    replystring.split (".", QString::SkipEmptyParts);

  if (versiondigits.length () == 3)
    {

      major = versiondigits.at (0).toInt (&majorok, 10);
      minor = versiondigits.at (1).toInt (&minorok, 10);
      patch = versiondigits.at (2).toInt (&patchok, 10);

      if (majorok == TRUE && minorok == TRUE && patchok == TRUE)
	{
	  if (major > SYSTESTER_MAJOR)
	    newversion = TRUE;
	  else if (major == SYSTESTER_MAJOR)
	    {
	      if (minor > SYSTESTER_MINOR)
		newversion = TRUE;
	      else if (minor == SYSTESTER_MINOR)
		{
		  if (patch > SYSTESTER_PATCH)
		    newversion = TRUE;
		}
	    }

	  error = FALSE;
	}
    }


  if (error == FALSE)
    {
      if (newversion == TRUE)
	{
	  int msgret = QMessageBox::information (this,
						 tr
						 ("New version available!"),
						 tr
						 ("System Stability Tester has a new version available\nSwitch to downloads page?"),
						 QMessageBox::
						 Ok | QMessageBox::Cancel);

	  if (msgret == QMessageBox::Ok)
	    {
	      QDesktopServices::
		openUrl (QUrl
			 ("http://systester.sourceforge.net/downloads.php"));
	    }

	}
      else
	{
	  QMessageBox::information (this,
				    tr ("Latest version"),
				    tr
				    ("You have the latest version of System Stability Tester"),
				    QMessageBox::Ok);
	}
    }
  else
    {
      QMessageBox::warning (this,
			    tr ("Warning"),
			    tr
			    ("Check for a new version failed. Please check for a new version manually"),
			    QMessageBox::Ok);
    }

}

void
MainForm::aboutButton_clicked ()
{
  Splash->show ();
}

void
MainForm::FontsButton_clicked ()
{

  bool ok;

  globalfont = QFontDialog::getFont (&ok, globalfont, this);
  if (ok)
    {
      textLabel10->setFont (globalfont);
      textLabel11->setFont (globalfont);
      textLabel12->setFont (globalfont);
      textLabel13->setFont (globalfont);
      textLabel14->setFont (globalfont);
      textLabel15->setFont (globalfont);
      digits->setFont (globalfont);
      execBox->setFont (globalfont);
      algoBox->setFont (globalfont);
      threadsBox->setFont (globalfont);
      runButton->setFont (globalfont);
      modeButton->setFont (globalfont);
      FontsButton->setFont (globalfont);
      aboutButton->setFont (globalfont);
      flattrButton->setFont (globalfont);
      exitButton->setFont (globalfont);
      stopButton->setFont (globalfont);
      Terminal->setFont (globalfont);
      CPUString->setFont (globalfont);
      FreqString->setFont (globalfont);
      NCPUSString->setFont (globalfont);
      GMPVERString->setFont (globalfont);
      ILPString->setFont (globalfont);
      RAMString->setFont (globalfont);
      updateButton->setFont (globalfont);
    }
}


void
MainForm::flattrButton_clicked ()
{
  QDesktopServices::
    openUrl (QUrl
	     ("http://flattr.com/thing/497771/System-Stability-Tester",
	      QUrl::TolerantMode));
}


void
MainForm::stopButton_clicked ()
{
  stoppressed = TRUE;
  stopButton->setEnabled (FALSE);
  setCursor (Qt::WaitCursor);
}


void
MainForm::threadsBox_changed ()
{
  if (threadsBox->currentIndex () == 0)
    modeButton->setEnabled (FALSE);
  else
    modeButton->setEnabled (TRUE);
}
