#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QClipboard>
#include <QTreeWidget>

#include "romstatusexport.h"
#include "macros.h"
#include "options.h"
#include "gamelist.h"
#include "qmc2main.h"

// external global variables
extern MainWindow *qmc2MainWindow;
extern Options *qmc2Options;
extern QSettings *qmc2Config;
extern bool qmc2WidgetsEnabled;
extern QMap<QString, QTreeWidgetItem *> qmc2GamelistItemMap;
extern Gamelist *qmc2Gamelist;
extern bool qmc2ExportingROMStatus;
extern bool qmc2StopParser;

ROMStatusExporter::ROMStatusExporter(QWidget *parent)
  : QDialog(parent)
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: ROMStatusExporter::ROMStatusExporter(QWidget *parent = %1)").arg((qulonglong) parent));
#endif

  setupUi(this);

#if defined(QMC2_SDLMESS)
  comboBoxSortCriteria->setItemText(QMC2_SORTCRITERIA_DESCRIPTION, tr("Machine description"));
  comboBoxSortCriteria->setItemText(QMC2_SORTCRITERIA_MACHINENAME, tr("Machine name"));
#endif

  pushButtonExport->setEnabled(qmc2WidgetsEnabled);

  // restore settings
  comboBoxOutputFormat->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/OutputFormat", 0).toInt());
  toolButtonExportC->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportC", TRUE).toBool());
  toolButtonExportM->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportM", TRUE).toBool());
  toolButtonExportI->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportI", TRUE).toBool());
  toolButtonExportN->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportN", TRUE).toBool());
  toolButtonExportU->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportU", TRUE).toBool());
  comboBoxSortCriteria->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/SortCriteria", 0).toInt());
  comboBoxSortOrder->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/SortOrder", 0).toInt());
  checkBoxIncludeHeader->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/IncludeHeader", TRUE).toBool());
  checkBoxIncludeStatistics->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/IncludeStatistics", TRUE).toBool());
  checkBoxExportToClipboard->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportToClipboard", FALSE).toBool());
  checkBoxOverwriteBlindly->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/OverwriteBlindly", FALSE).toBool());
  lineEditASCIIFile->setText(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ASCIIFile", "data/tmp/rom-status.txt").toString());
  spinBoxASCIIColumnWidth->setValue(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ASCIIColumnWidth", 0).toInt());
  lineEditCSVFile->setText(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/CSVFile", "data/tmp/rom-status.csv").toString());
  lineEditCSVSeparator->setText(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/CSVSeparator", ";").toString());
  lineEditCSVDelimiter->setText(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/CSVDelimiter", "\"").toString());
  lineEditHTMLFile->setText(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/HTMLFile", "data/tmp/rom-status.html").toString());
  spinBoxHTMLBorderWidth->setValue(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/HTMLBorderWidth", 1).toInt());

  progressBarExport->reset();
}

ROMStatusExporter::~ROMStatusExporter()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, "DEBUG: ROMStatusExporter::~ROMStatusExporter()");
#endif

}

void ROMStatusExporter::closeEvent(QCloseEvent *e)
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: ROMStatusExporter::closeEvent(QCloseEvent *e = %1)").arg((qulonglong) e));
#endif

  // save settings
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/OutputFormat", comboBoxOutputFormat->currentIndex());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportC", toolButtonExportC->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportM", toolButtonExportM->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportI", toolButtonExportI->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportN", toolButtonExportN->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportU", toolButtonExportU->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/SortCriteria", comboBoxSortCriteria->currentIndex());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/SortOrder", comboBoxSortOrder->currentIndex());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/IncludeHeader", checkBoxIncludeHeader->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/IncludeStatistics", checkBoxIncludeStatistics->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ExportToClipboard", checkBoxExportToClipboard->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/OverwriteBlindly", checkBoxOverwriteBlindly->isChecked());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ASCIIFile", lineEditASCIIFile->text());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/ASCIIColumnWidth", spinBoxASCIIColumnWidth->value());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/CSVFile", lineEditCSVFile->text());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/CSVSeparator", lineEditCSVSeparator->text());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/CSVDelimiter", lineEditCSVDelimiter->text());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/HTMLFile", lineEditHTMLFile->text());
  qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ROMStatusExporter/HTMLBorderWidth", spinBoxHTMLBorderWidth->value());

  e->accept();
}

void ROMStatusExporter::exportToASCII()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: ROMStatusExporter::exportToASCII()"));
#endif

  QFile exportFile(lineEditASCIIFile->text());
  QString clipboardBuffer;
  QTextStream ts;
  if ( !checkBoxExportToClipboard->isChecked() ) {
    if ( !checkBoxOverwriteBlindly->isChecked() && exportFile.exists() ) {
      switch ( QMessageBox::question(this, tr("Confirm"), tr("Overwrite existing file?"), QMessageBox::Yes, QMessageBox::No) ) {
        case QMessageBox::Yes:
          break;

        case QMessageBox::No:
        default:
          return;
          break;
      }
    }

    if ( exportFile.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      qmc2ExportingROMStatus = TRUE;
      ts.setDevice(&exportFile);
      qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("exporting ROM status in ASCII format to '%1'").arg(QFileInfo(exportFile).filePath()));
    } else {
      qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("WARNING: can't open ASCII export file '%1' for writing, please check permissions").arg(QFileInfo(exportFile).filePath()));
      return;
    }
  } else {
    qmc2ExportingROMStatus = TRUE;
    ts.setString(&clipboardBuffer);
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("exporting ROM status in ASCII format to clipboard"));
  }

  frameExportParams->setEnabled(FALSE);

  progressBarExport->setRange(0, qmc2Gamelist->numGames);
  progressBarExport->reset();
  progressBarExport->setValue(0);

  int maxLength = 0;
  QStringList headerStrings;
  headerStrings << tr("Emulator")
                << tr("Date")
                << tr("Time")
#if defined(QMC2_SDLMAME)
                << tr("Total games")
#elif defined(QMC2_SDLMESS)
                << tr("Total machines")
#endif
                << tr("Correct")
                << tr("Mostly correct")
                << tr("Incorrect")
                << tr("Not found")
                << tr("Unknown");
  foreach (QString s, headerStrings)
    if ( s.length() > maxLength )
      maxLength = s.length();
  maxLength += 2;
    
  if ( checkBoxIncludeHeader->isChecked() ) {
    QString qmc2Version(QString(XSTR(MAJOR)) + "." + QString(XSTR(MINOR)));
#ifdef BETA
    qmc2Version += ".b" + QString(XSTR(BETA));
#endif
    ts << tr("ROM Status Export - created by QMC2 %1").arg(qmc2Version) << "\n"
       << QString().leftJustified(tr("ROM Status Export - created by QMC2 %1").arg(qmc2Version).length(), '-', TRUE) << "\n\n";
#if defined(QMC2_SDLMAME)
    QString emulatorTarget = "SDLMAME";
#elif defined(QMC2_SDLMESS)
    QString emulatorTarget = "SDLMESS";
#else
    QString emulatorTarget = tr("unknown");
#endif
    ts << tr("Emulator") << " " << QString().leftJustified(maxLength - tr("Emulator").length(), '.', TRUE) << " " << emulatorTarget << " " << qmc2Gamelist->emulatorVersion << "\n";
    ts << tr("Date") << " " << QString().leftJustified(maxLength - tr("Date").length(), '.', TRUE) << " " << QDate::currentDate().toString() << "\n";
    ts << tr("Time") << " " << QString().leftJustified(maxLength - tr("Time").length(), '.', TRUE) << " " << QTime::currentTime().toString() << "\n\n";
  }

  if ( checkBoxIncludeStatistics->isChecked() ) {
    ts << tr("Overall ROM Status") << "\n"
       << QString().leftJustified(tr("Overall ROM Status").length(), '-', TRUE) << "\n\n";
#if defined(QMC2_SDLMAME)
    ts << tr("Total games") << " " << QString().leftJustified(maxLength - tr("Total games").length(), '.', TRUE) << " " << qmc2Gamelist->numGames << "\n";
#elif defined(QMC2_SDLMESS)
    ts << tr("Total machines") << " " << QString().leftJustified(maxLength - tr("Total machines").length(), '.', TRUE) << " " << qmc2Gamelist->numGames << "\n";
#endif
    ts << tr("Correct") << " " << QString().leftJustified(maxLength - tr("Correct").length(), '.', TRUE) << " " << qmc2Gamelist->numCorrectGames << "\n";
    ts << tr("Mostly correct") << " " << QString().leftJustified(maxLength - tr("Mostly correct").length(), '.', TRUE) << " " << qmc2Gamelist->numMostlyCorrectGames << "\n";
    ts << tr("Incorrect") << " " << QString().leftJustified(maxLength - tr("Incorrect").length(), '.', TRUE) << " " << qmc2Gamelist->numIncorrectGames << "\n";
    ts << tr("Not found") << " " << QString().leftJustified(maxLength - tr("Not found").length(), '.', TRUE) << " " << qmc2Gamelist->numNotFoundGames << "\n";
    ts << tr("Unknown") << " " << QString().leftJustified(maxLength - tr("Unknown").length(), '.', TRUE) << " " << qmc2Gamelist->numUnknownGames << "\n\n";
  }

  ts << tr("Detailed ROM Status") << "\n"
     << QString().leftJustified(tr("Detailed ROM Status").length(), '-', TRUE) << "\n\n";

  // create a sorted multi-map as export data...
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("sorting, filtering and analyzing export data"));

  int maxDescriptionColumnWidth = 0;
  int maxNameColumnWidth = 0;
  int maxStateColumnWidth = 0;
  int maxManufacturerColumnWidth = 0;
  int maxYearColumnWidth = 0;

  QMapIterator<QString, QTreeWidgetItem *> it(qmc2GamelistItemMap);
  QMultiMap<QString, QTreeWidgetItem *> exportMap;
  int i = 0;
  while ( it.hasNext() && !qmc2StopParser ) {
    progressBarExport->setValue(++i);
    qApp->processEvents();
    it.next();

    QString translatedState;
    switch ( it.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME).at(0).toAscii() ) {
      case QMC2_ROMSTATE_CHAR_C:
        if ( !toolButtonExportC->isChecked() )
          continue;
        else
          translatedState = tr("correct");
        break;

      case QMC2_ROMSTATE_CHAR_M:
        if ( !toolButtonExportM->isChecked() )
          continue;
        else
          translatedState = tr("mostly correct");
        break;

      case QMC2_ROMSTATE_CHAR_I:
        if ( !toolButtonExportI->isChecked() )
          continue;
        else
          translatedState = tr("incorrect");
        break;

      case QMC2_ROMSTATE_CHAR_N:
        if ( !toolButtonExportN->isChecked() )
          continue;
        else
          translatedState = tr("not found");
        break;

      case QMC2_ROMSTATE_CHAR_U:
      default:
        if ( !toolButtonExportU->isChecked() )
          continue;
        else
          translatedState = tr("unknown");
        break;
    }

    switch ( comboBoxSortCriteria->currentIndex() ) {
      case QMC2_SORT_BY_DESCRIPTION:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_GAME), it.value());
        break;

      case QMC2_SORT_BY_ROM_STATE:
        exportMap.insert(it.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME), it.value());
        break;

      case QMC2_SORT_BY_YEAR:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_YEAR), it.value());
        break;

      case QMC2_SORT_BY_MANUFACTURER:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_MANU), it.value());
        break;

      case QMC2_SORT_BY_NAME:
        exportMap.insert(it.key(), it.value());
        break;

      default:
        break;
    }

    if ( it.value()->text(QMC2_GAMELIST_COLUMN_GAME).length() > maxDescriptionColumnWidth )
      maxDescriptionColumnWidth = it.value()->text(QMC2_GAMELIST_COLUMN_GAME).length();
    if ( it.key().length() > maxNameColumnWidth )
      maxNameColumnWidth = it.key().length();
    if ( it.value()->text(QMC2_GAMELIST_COLUMN_MANU).length() > maxManufacturerColumnWidth )
      maxManufacturerColumnWidth = it.value()->text(QMC2_GAMELIST_COLUMN_MANU).length();
    if ( it.value()->text(QMC2_GAMELIST_COLUMN_YEAR).length() > maxYearColumnWidth )
      maxYearColumnWidth = it.value()->text(QMC2_GAMELIST_COLUMN_YEAR).length();
    if ( translatedState.length() > maxStateColumnWidth )
      maxStateColumnWidth = translatedState.length();
  }

  // truncate column widths if applicable...
  if ( spinBoxASCIIColumnWidth->value() > 0 ) {
    maxDescriptionColumnWidth = MIN(maxDescriptionColumnWidth, spinBoxASCIIColumnWidth->value());
    maxNameColumnWidth = MIN(maxNameColumnWidth, spinBoxASCIIColumnWidth->value());
    maxManufacturerColumnWidth = MIN(maxManufacturerColumnWidth, spinBoxASCIIColumnWidth->value());
    maxYearColumnWidth = MIN(maxYearColumnWidth, spinBoxASCIIColumnWidth->value());
    maxStateColumnWidth = MIN(maxStateColumnWidth, spinBoxASCIIColumnWidth->value());
  }

  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (sorting, filtering and analyzing export data)"));
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("writing export data"));

  ts << tr("Name").leftJustified(maxNameColumnWidth, ' ', TRUE) << "  "
     << tr("Status").leftJustified(maxStateColumnWidth, ' ', TRUE) << "  "
     << tr("Description").leftJustified(maxDescriptionColumnWidth, ' ', TRUE) << "  "
     << tr("Year").leftJustified(maxYearColumnWidth, ' ', TRUE) << "  "
     << tr("Manufacturer").leftJustified(maxManufacturerColumnWidth, ' ', TRUE) << "\n";
  ts << QString("-").leftJustified(maxNameColumnWidth, '-', TRUE) << "  "
     << QString("-").leftJustified(maxStateColumnWidth, '-', TRUE) << "  "
     << QString("-").leftJustified(maxDescriptionColumnWidth, '-', TRUE) << "  "
     << QString("-").leftJustified(maxYearColumnWidth, '-', TRUE) << "  "
     << QString("-").leftJustified(maxManufacturerColumnWidth, '-', TRUE) << "\n";

  QMapIterator<QString, QTreeWidgetItem *> itExport(exportMap);
  i = 0;
  bool ascendingOrder = (comboBoxSortOrder->currentIndex() == 0);
  bool showMoreChars = ( spinBoxASCIIColumnWidth->value() > 3 );
  if ( !ascendingOrder )
    itExport.toBack();
  while ( ( ( ascendingOrder && itExport.hasNext() ) || ( !ascendingOrder && itExport.hasPrevious() ) ) && !qmc2StopParser ) {
    progressBarExport->setValue(++i);
    qApp->processEvents();

    if ( ascendingOrder )
      itExport.next();
    else
      itExport.previous();

    QString s = itExport.value()->text(QMC2_GAMELIST_COLUMN_NAME);
    if ( showMoreChars && s.length() > maxNameColumnWidth )
      ts << s.left(maxNameColumnWidth - 3).leftJustified(maxNameColumnWidth, '.', TRUE) << "  ";
    else
      ts << s.leftJustified(maxNameColumnWidth, ' ', TRUE) << "  ";
    switch ( itExport.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME).at(0).toAscii() ) {
      case QMC2_ROMSTATE_CHAR_C:
        s = tr("correct");
        break;

      case QMC2_ROMSTATE_CHAR_M:
	s = tr("mostly correct");
        break;

      case QMC2_ROMSTATE_CHAR_I:
	s = tr("incorrect");
        break;

      case QMC2_ROMSTATE_CHAR_N:
	s = tr("not found");
        break;

      case QMC2_ROMSTATE_CHAR_U:
      default:
	s = tr("unknown");
        break;
    }
    if ( showMoreChars && s.length() > maxStateColumnWidth )
      ts << s.left(maxStateColumnWidth - 3).leftJustified(maxStateColumnWidth, '.', TRUE) << "  ";
    else
      ts << s.leftJustified(maxStateColumnWidth, ' ', TRUE) << "  ";
    s = itExport.value()->text(QMC2_GAMELIST_COLUMN_GAME);
    if ( showMoreChars && s.length() > maxDescriptionColumnWidth )
      ts << s.left(maxDescriptionColumnWidth - 3).leftJustified(maxDescriptionColumnWidth, '.', TRUE) << "  ";
    else
      ts << s.leftJustified(maxDescriptionColumnWidth, ' ', TRUE) << "  ";
    s = itExport.value()->text(QMC2_GAMELIST_COLUMN_YEAR);
    if ( showMoreChars && s.length() > maxYearColumnWidth )
      ts << s.left(maxYearColumnWidth - 3).leftJustified(maxYearColumnWidth, '.', TRUE) << "  ";
    else
      ts << s.leftJustified(maxYearColumnWidth, ' ', TRUE) << "  ";
    s = itExport.value()->text(QMC2_GAMELIST_COLUMN_MANU);
    if ( showMoreChars && s.length() > maxManufacturerColumnWidth )
      ts << s.left(maxManufacturerColumnWidth - 3).leftJustified(maxManufacturerColumnWidth, '.', TRUE) << "\n";
    else
      ts << s.leftJustified(maxManufacturerColumnWidth, ' ', TRUE) << "\n";
  }

  progressBarExport->reset();
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (writing export data)"));

  if ( checkBoxExportToClipboard->isChecked() ) {
    qApp->clipboard()->setText(clipboardBuffer);
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (exporting ROM status in ASCII format to clipboard)"));
  } else {
    exportFile.close();
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (exporting ROM status in ASCII format to '%1')").arg(QFileInfo(exportFile).filePath()));
  }

  frameExportParams->setEnabled(TRUE);
  qmc2ExportingROMStatus = FALSE;
}

void ROMStatusExporter::exportToCSV()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: ROMStatusExporter::exportToCSV()"));
#endif

  QFile exportFile(lineEditCSVFile->text());
  QString clipboardBuffer;
  QTextStream ts;
  if ( !checkBoxExportToClipboard->isChecked() ) {
    if ( !checkBoxOverwriteBlindly->isChecked() && exportFile.exists() ) {
      switch ( QMessageBox::question(this, tr("Confirm"), tr("Overwrite existing file?"), QMessageBox::Yes, QMessageBox::No) ) {
        case QMessageBox::Yes:
          break;

        case QMessageBox::No:
        default:
          return;
          break;
      }
    }

    if ( exportFile.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      qmc2ExportingROMStatus = TRUE;
      ts.setDevice(&exportFile);
      qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("exporting ROM status in CSV format to '%1'").arg(QFileInfo(exportFile).filePath()));
    } else {
      qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("WARNING: can't open CSV export file '%1' for writing, please check permissions").arg(QFileInfo(exportFile).filePath()));
      return;
    }
  } else {
    qmc2ExportingROMStatus = TRUE;
    ts.setString(&clipboardBuffer);
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("exporting ROM status in CSV format to clipboard"));
  }

  frameExportParams->setEnabled(FALSE);

  progressBarExport->setRange(0, qmc2Gamelist->numGames);
  progressBarExport->reset();
  progressBarExport->setValue(0);

  QString sep = lineEditCSVSeparator->text();
  QString del = lineEditCSVDelimiter->text();

  if ( checkBoxIncludeHeader->isChecked() ) {
    QString qmc2Version(QString(XSTR(MAJOR)) + "." + QString(XSTR(MINOR)));
#ifdef BETA
    qmc2Version += ".b" + QString(XSTR(BETA));
#endif
    ts << del << tr("ROM Status Export - created by QMC2 %1").arg(qmc2Version) << del << "\n" << del << del << "\n";
#if defined(QMC2_SDLMAME)
    QString emulatorTarget = "SDLMAME";
#elif defined(QMC2_SDLMESS)
    QString emulatorTarget = "SDLMESS";
#else
    QString emulatorTarget = tr("unknown");
#endif
    ts << del << tr("Emulator") << del << sep << del << emulatorTarget << " " << qmc2Gamelist->emulatorVersion << del << "\n";
    ts << del << tr("Date") << del << sep << del << QDate::currentDate().toString() << del << "\n";
    ts << del << tr("Time") << del << sep << del << QTime::currentTime().toString() << del << "\n" << del << del << "\n";
  }

  if ( checkBoxIncludeStatistics->isChecked() ) {
    ts << del << tr("Overall ROM Status") << del << "\n" << del << del << "\n";
#if defined(QMC2_SDLMAME)
    ts << del << tr("Total games") << del << sep << del << qmc2Gamelist->numGames << del << "\n";
#elif defined(QMC2_SDLMESS)
    ts << del << tr("Total machines") << del << sep << del << qmc2Gamelist->numGames << del << "\n";
#endif
    ts << del << tr("Correct") << del << sep << del << qmc2Gamelist->numCorrectGames << del << "\n";
    ts << del << tr("Mostly correct") << del << sep << del << qmc2Gamelist->numMostlyCorrectGames << del << "\n";
    ts << del << tr("Incorrect") << del << sep << del << qmc2Gamelist->numIncorrectGames << del << "\n";
    ts << del << tr("Not found") << del << sep << del << qmc2Gamelist->numNotFoundGames << del << "\n";
    ts << del << tr("Unknown") << del << sep << del << qmc2Gamelist->numUnknownGames << del << "\n" << del << del << "\n";
  }

  ts << del << tr("Detailed ROM Status") << del << "\n" << del << del << "\n";

  // create a sorted multi-map as export data...
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("sorting and filtering export data"));

  QMapIterator<QString, QTreeWidgetItem *> it(qmc2GamelistItemMap);
  QMultiMap<QString, QTreeWidgetItem *> exportMap;
  int i = 0;
  while ( it.hasNext() && !qmc2StopParser ) {
    progressBarExport->setValue(++i);
    qApp->processEvents();
    it.next();

    switch ( comboBoxSortCriteria->currentIndex() ) {
      case QMC2_SORT_BY_DESCRIPTION:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_GAME), it.value());
        break;

      case QMC2_SORT_BY_ROM_STATE:
        exportMap.insert(it.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME), it.value());
        break;

      case QMC2_SORT_BY_YEAR:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_YEAR), it.value());
        break;

      case QMC2_SORT_BY_MANUFACTURER:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_MANU), it.value());
        break;

      case QMC2_SORT_BY_NAME:
        exportMap.insert(it.key(), it.value());
        break;

      default:
        break;
    }
  }

  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (sorting and filtering export data)"));
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("writing export data"));

  ts << del << tr("Name") << del << sep
     << del << tr("Status") << del << sep
     << del << tr("Description") << del << sep
     << del << tr("Year") << del << sep
     << del << tr("Manufacturer") << del << "\n" << del << del << "\n";

  QMapIterator<QString, QTreeWidgetItem *> itExport(exportMap);
  i = 0;
  bool ascendingOrder = (comboBoxSortOrder->currentIndex() == 0);
  if ( !ascendingOrder )
    itExport.toBack();
  while ( ( ( ascendingOrder && itExport.hasNext() ) || ( !ascendingOrder && itExport.hasPrevious() ) ) && !qmc2StopParser ) {
    progressBarExport->setValue(++i);
    qApp->processEvents();

    if ( ascendingOrder )
      itExport.next();
    else
      itExport.previous();

    ts << del << itExport.value()->text(QMC2_GAMELIST_COLUMN_NAME) << del << sep;
    switch ( itExport.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME).at(0).toAscii() ) {
      case QMC2_ROMSTATE_CHAR_C:
        ts << del << tr("correct") << del << sep;
        break;

      case QMC2_ROMSTATE_CHAR_M:
	ts << del << tr("mostly correct") << del << sep;
        break;

      case QMC2_ROMSTATE_CHAR_I:
	ts << del << tr("incorrect") << del << sep;
        break;

      case QMC2_ROMSTATE_CHAR_N:
	ts << del << tr("not found") << del << sep;
        break;

      case QMC2_ROMSTATE_CHAR_U:
      default:
	ts << del << tr("unknown") << del << sep;
        break;
    }
    ts << del << itExport.value()->text(QMC2_GAMELIST_COLUMN_GAME) << del << sep;
    ts << del << itExport.value()->text(QMC2_GAMELIST_COLUMN_YEAR) << del << sep;
    ts << del << itExport.value()->text(QMC2_GAMELIST_COLUMN_MANU) << del << "\n";
  }

  progressBarExport->reset();
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (writing export data)"));

  if ( checkBoxExportToClipboard->isChecked() ) {
    qApp->clipboard()->setText(clipboardBuffer);
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (exporting ROM status in CSV format to clipboard)"));
  } else {
    exportFile.close();
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (exporting ROM status in CSV format to '%1')").arg(QFileInfo(exportFile).filePath()));
  }

  frameExportParams->setEnabled(TRUE);
  qmc2ExportingROMStatus = FALSE;
}

void ROMStatusExporter::exportToHTML()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: ROMStatusExporter::exportToHTML()"));
#endif

  QFile exportFile(lineEditHTMLFile->text());
  QString clipboardBuffer;
  QTextStream ts;
  if ( !checkBoxExportToClipboard->isChecked() ) {
    if ( !checkBoxOverwriteBlindly->isChecked() && exportFile.exists() ) {
      switch ( QMessageBox::question(this, tr("Confirm"), tr("Overwrite existing file?"), QMessageBox::Yes, QMessageBox::No) ) {
        case QMessageBox::Yes:
          break;

        case QMessageBox::No:
        default:
          return;
          break;
      }
    }

    if ( exportFile.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      qmc2ExportingROMStatus = TRUE;
      ts.setDevice(&exportFile);
      qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("exporting ROM status in HTML format to '%1'").arg(QFileInfo(exportFile).filePath()));
    } else {
      qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("WARNING: can't open HTML export file '%1' for writing, please check permissions").arg(QFileInfo(exportFile).filePath()));
      return;
    }
  } else {
    qmc2ExportingROMStatus = TRUE;
    ts.setString(&clipboardBuffer);
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("exporting ROM status in HTML format to clipboard"));
  }

  frameExportParams->setEnabled(FALSE);

  progressBarExport->setRange(0, qmc2Gamelist->numGames);
  progressBarExport->reset();
  progressBarExport->setValue(0);

  QString qmc2Version(QString(XSTR(MAJOR)) + "." + QString(XSTR(MINOR)));
#ifdef BETA
  qmc2Version += ".b" + QString(XSTR(BETA));
#endif

  ts << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
     << "<html>\n"
     << "<head>\n"
     << "  <meta http-equiv=\"CONTENT-TYPE\" content=\"text/html; charset=utf-8\">\n"
     << "  <title>" << tr("ROM Status Export - created by QMC2 %1").arg(qmc2Version) << "</title>\n"
     << "</head>\n"
     << "<body style=\"color: black; background-color: lightyellow;\" dir=\"ltr\" alink=\"#111111\" link=\"#111111\" vlink=\"#999999\">\n";

  if ( checkBoxIncludeHeader->isChecked() ) {
#if defined(QMC2_SDLMAME)
    QString emulatorTarget = "SDLMAME";
#elif defined(QMC2_SDLMESS)
    QString emulatorTarget = "SDLMESS";
#else
    QString emulatorTarget = tr("unknown");
#endif
    ts << "<h3>" << tr("ROM Status Export - created by QMC2 %1").arg(qmc2Version) << "</h3>\n"
       << "<p>\n"
       << "<table border=\"" << spinBoxHTMLBorderWidth->value() << "\">\n"
       << "<tr>\n"
       << "  <td nowrap>" << tr("Emulator") << "</td><td nowrap>" << emulatorTarget << " " << qmc2Gamelist->emulatorVersion << "</td>\n"
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Date") << "</td><td nowrap>" << QDate::currentDate().toString() << "</td>\n"
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Time") << "</td><td nowrap>" << QTime::currentTime().toString() << "</td>\n"
       << "</tr>\n"
       << "</table>\n"
       << "</p>\n";
  }

  if ( checkBoxIncludeStatistics->isChecked() ) {
    ts << "<h3>" << tr("Overall ROM Status") << "</h3>\n"
       << "<p>\n"
       << "<table border=\"" << spinBoxHTMLBorderWidth->value() << "\">\n"
       << "<tr>\n"
#if defined(QMC2_SDLMAME)
       << "  <td nowrap>" << tr("Total games") << "</td><td nowrap>" << qmc2Gamelist->numGames << "</td>\n"
#elif defined(QMC2_SDLMESS)
       << "  <td nowrap>" << tr("Total machines") << "</td><td nowrap>" << qmc2Gamelist->numGames << "</td>\n"
#endif
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Correct") << "</td><td nowrap>" << qmc2Gamelist->numCorrectGames << "</td>\n"
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Mostly correct") << "</td><td nowrap>" << qmc2Gamelist->numMostlyCorrectGames << "</td>\n"
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Incorrect") << "</td><td nowrap>" << qmc2Gamelist->numIncorrectGames << "</td>\n"
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Not found") << "</td><td nowrap>" << qmc2Gamelist->numNotFoundGames << "</td>\n"
       << "</tr>\n<tr>\n"
       << "  <td nowrap>" << tr("Unknown") << "</td><td nowrap>" << qmc2Gamelist->numUnknownGames << "</td>\n"
       << "</tr>\n"
       << "</table>\n"
       << "</p>\n";
  }

  ts << "<h3>" << tr("Detailed ROM Status") << "</h3>\n"
     << "<p>\n";

  // create a sorted multi-map as export data...
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("sorting and filtering export data"));

  QMapIterator<QString, QTreeWidgetItem *> it(qmc2GamelistItemMap);
  QMultiMap<QString, QTreeWidgetItem *> exportMap;
  int i = 0;
  while ( it.hasNext() && !qmc2StopParser ) {
    progressBarExport->setValue(++i);
    qApp->processEvents();
    it.next();

    switch ( comboBoxSortCriteria->currentIndex() ) {
      case QMC2_SORT_BY_DESCRIPTION:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_GAME), it.value());
        break;

      case QMC2_SORT_BY_ROM_STATE:
        exportMap.insert(it.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME), it.value());
        break;

      case QMC2_SORT_BY_YEAR:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_YEAR), it.value());
        break;

      case QMC2_SORT_BY_MANUFACTURER:
        exportMap.insert(it.value()->text(QMC2_GAMELIST_COLUMN_MANU), it.value());
        break;

      case QMC2_SORT_BY_NAME:
        exportMap.insert(it.key(), it.value());
        break;

      default:
        break;
    }
  }

  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (sorting and filtering export data)"));
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("writing export data"));

  ts << "<table border=\"" << spinBoxHTMLBorderWidth->value() << "\">\n"
     << "<tr>\n"
     << "  <td nowrap><b>" << tr("Name") << "</b></td><td nowrap><b>" << tr("Status") << "</b></td><td nowrap><b>" << tr("Description") << "</b></td><td nowrap><b>" << tr("Year") << "</b></td><td nowrap><b>" << tr("Manufacturer") << "</b></td nowrap>\n"
     << "</tr>\n";

  QMapIterator<QString, QTreeWidgetItem *> itExport(exportMap);
  i = 0;
  bool ascendingOrder = (comboBoxSortOrder->currentIndex() == 0);
  if ( !ascendingOrder )
    itExport.toBack();
  while ( ( ( ascendingOrder && itExport.hasNext() ) || ( !ascendingOrder && itExport.hasPrevious() ) ) && !qmc2StopParser ) {
    progressBarExport->setValue(++i);
    qApp->processEvents();

    if ( ascendingOrder )
      itExport.next();
    else
      itExport.previous();

    ts << "<tr>\n"
       << "  <td valign=\"top\">" << itExport.value()->text(QMC2_GAMELIST_COLUMN_NAME) << "</td>";

    switch ( itExport.value()->whatsThis(QMC2_GAMELIST_COLUMN_GAME).at(0).toAscii() ) {
      case QMC2_ROMSTATE_CHAR_C:
        ts << "<td valign=\"top\">" << tr("correct") << "</td>";
        break;

      case QMC2_ROMSTATE_CHAR_M:
	ts << "<td valign=\"top\">" << tr("mostly correct") << "</td>";
        break;

      case QMC2_ROMSTATE_CHAR_I:
	ts << "<td valign=\"top\">" << tr("incorrect") << "</td>";
        break;

      case QMC2_ROMSTATE_CHAR_N:
	ts << "<td valign=\"top\">" << tr("not found") << "</td>";
        break;

      case QMC2_ROMSTATE_CHAR_U:
      default:
	ts << "<td valign=\"top\">" << tr("unknown") << "</td>";
        break;
    }
    ts << "<td valign=\"top\">" << itExport.value()->text(QMC2_GAMELIST_COLUMN_GAME) << "</td>"
       << "<td valign=\"top\">" << itExport.value()->text(QMC2_GAMELIST_COLUMN_YEAR) << "</td>"
       << "<td valign=\"top\">" << itExport.value()->text(QMC2_GAMELIST_COLUMN_MANU) << "</td>\n"
       << "</tr>\n";
  }

  ts << "</table>\n</p>\n</html>";

  progressBarExport->reset();
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (writing export data)"));

  if ( checkBoxExportToClipboard->isChecked() ) {
    qApp->clipboard()->setText(clipboardBuffer);
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (exporting ROM status in HTML format to clipboard)"));
  } else {
    exportFile.close();
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("done (exporting ROM status in HTML format to '%1')").arg(QFileInfo(exportFile).filePath()));
  }

  frameExportParams->setEnabled(TRUE);
  qmc2ExportingROMStatus = FALSE;
}

void ROMStatusExporter::on_toolButtonBrowseASCIIFile_clicked()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, "DEBUG: ROMStatusExporter::on_toolButtonBrowseASCIIFile_clicked()");
#endif

  QString s = QFileDialog::getOpenFileName(this, tr("Choose ASCII export file"), lineEditASCIIFile->text(), tr("All files (*)"));
  if ( !s.isNull() )
    lineEditASCIIFile->setText(s);
  raise();
}

void ROMStatusExporter::on_toolButtonBrowseCSVFile_clicked()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, "DEBUG: ROMStatusExporter::on_toolButtonBrowseCSVFile_clicked()");
#endif

  QString s = QFileDialog::getOpenFileName(this, tr("Choose CSV export file"), lineEditCSVFile->text(), tr("All files (*)"));
  if ( !s.isNull() )
    lineEditCSVFile->setText(s);
  raise();
}

void ROMStatusExporter::on_toolButtonBrowseHTMLFile_clicked()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, "DEBUG: ROMStatusExporter::on_toolButtonBrowseHTMLFile_clicked()");
#endif

  QString s = QFileDialog::getOpenFileName(this, tr("Choose HTML export file"), lineEditHTMLFile->text(), tr("All files (*)"));
  if ( !s.isNull() )
    lineEditHTMLFile->setText(s);
  raise();
}

void ROMStatusExporter::on_pushButtonExport_clicked()
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, "DEBUG: ROMStatusExporter::on_pushButtonExport_clicked()");
#endif

  if ( !qmc2Gamelist ) {
    qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("gamelist is not ready, please wait"));
    return;
  }

  switch ( comboBoxOutputFormat->currentIndex() ) {
    case QMC2_ROMSTATUSEXPORT_FORMAT_ASCII_INDEX:
      exportToASCII();
      break;

    case QMC2_ROMSTATUSEXPORT_FORMAT_CSV_INDEX:
      exportToCSV();
      break;

    case QMC2_ROMSTATUSEXPORT_FORMAT_HTML_INDEX:
      exportToHTML();
      break;

    default:
      break;
  }
}

void ROMStatusExporter::on_comboBoxOutputFormat_currentIndexChanged(int index)
{
#ifdef QMC2_DEBUG
  qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: ROMStatusExporter::on_comboBoxOutputFormat_currentIndexChanged(int index = %1)").arg(index));
#endif

  stackedWidgetOutputParams->setCurrentIndex(index);
}
