#include "ConfigDialog.h"
#include "ConfigData.h"
#include <QComboBox>
#include <QTableWidgetItem>
#include <QTableWidget>
#include <QDebug>

ConfigDialog::ConfigDialog() : curTab(NULL) {

   main.setupUi(this);
   QDialog * temp = new QDialog();
   main.tabWidget->addTab(temp, tr("Preferences"));
   prefs.setupUi(temp);
   prefs.previewSizeCombo->addItem("640x480");
   prefs.previewSizeCombo->addItem("320x240");

   temp = new QDialog();
   main.tabWidget->addTab(temp, tr("Destination"));
   destdir.setupUi(temp);

   temp = new QDialog();
   main.tabWidget->addTab(temp, tr("Left Camera"));
   leftcam.setupUi(temp);

   temp = new QDialog();
   main.tabWidget->addTab(temp, tr("Right Camera"));
   rightcam.setupUi(temp);

   QTabWidget * uk1104 = new QTabWidget();
   main.tabWidget->addTab(uk1104, tr("UK1104"));
   temp = new QDialog();
   uk1104->addTab(temp, tr("Identify"));
   uk1104id.setupUi(temp);

   temp = new QDialog();
   uk1104->addTab(temp, tr("Relays"));
   uk1104relay.setupUi(temp);

   temp = new QDialog();
   uk1104->addTab(temp, tr("Digital Input"));
   uk1104input.setupUi(temp);
   uk1104input.channelValuePressed->addItem(tr("zero"));
   uk1104input.channelValuePressed->addItem(tr("one"));

   QTabWidget * timing = new QTabWidget();
   main.tabWidget->addTab(timing, tr("Timing"));

   QStringList col_hdr;
   col_hdr << tr("Millisecond") << tr("Action");

   temp = new QDialog();
   timing->addTab(temp, tr("Lights"));
   lights_prog.setupUi(temp);
   lights_prog.downloadTimeLabel->hide();
   lights_prog.constSpinBox->hide();
   lights_prog.plusLabel->hide();
   lights_prog.perImageSpinBox->hide();
   lights_prog.programTable->setHorizontalHeaderLabels(col_hdr);
   lights_prog.programTable->horizontalHeader()->setStretchLastSection(true);
   lights_prog.programTitleLabel->setText(tr("Timing for lights"));

   temp = new QDialog();
   timing->addTab(temp, tr("Picture"));
   cam_prog.setupUi(temp);
   cam_prog.downloadTimeLabel->hide();
   cam_prog.constSpinBox->hide();
   cam_prog.plusLabel->hide();
   cam_prog.perImageSpinBox->hide();
   cam_prog.programTable->setHorizontalHeaderLabels(col_hdr);
   cam_prog.programTable->horizontalHeader()->setStretchLastSection(true);
   cam_prog.programTitleLabel->setText(tr("Timing to just take pictures."));

   temp = new QDialog();
   timing->addTab(temp, tr("Download"));
   download_prog.setupUi(temp);
   download_prog.programTable->setHorizontalHeaderLabels(col_hdr);
   download_prog.programTable->horizontalHeader()->setStretchLastSection(true);
   download_prog.programTitleLabel->
      setText(tr("Timing to take pictures then download."));

   connect(
      lights_prog.programTable,
      SIGNAL(currentCellChanged(int, int, int, int)),
      this,
      SLOT(editProgramItem(int, int, int, int)));

   connect(
      lights_prog.programTable,
      SIGNAL(itemChanged(QTableWidgetItem*)),
      this,
      SLOT(maybeAddRow(QTableWidgetItem*)));

   connect(
      cam_prog.programTable,
      SIGNAL(currentCellChanged(int, int, int, int)),
      this,
      SLOT(editProgramItem(int, int, int, int)));

   connect(
      cam_prog.programTable,
      SIGNAL(itemChanged(QTableWidgetItem*)),
      this,
      SLOT(maybeAddRow(QTableWidgetItem*)));

   connect(
      download_prog.programTable,
      SIGNAL(currentCellChanged(int, int, int, int)),
      this,
      SLOT(editProgramItem(int, int, int, int)));

   connect(
      download_prog.programTable,
      SIGNAL(itemChanged(QTableWidgetItem*)),
      this,
      SLOT(maybeAddRow(QTableWidgetItem*)));
}

ConfigDialog::~ConfigDialog() {
}

void
ConfigDialog::PopUp() {

   // Set all the fields from the ConfigData class instance.

   ConfigData * c = ConfigData::GetConfig();
   uk1104id.vendorIdEdit->setText(c->UK1104Vendor());
   uk1104id.modelIdEdit->setText(c->UK1104Model());
   uk1104id.uk1104IdCodeEdit->setText(c->UK1104IdCode());
   uk1104id.initCommandEdit->setPlainText(c->UK1104Initialize().join("\n"));
   uk1104relay.lightsOnText->setPlainText(c->UK1104TurnOnLights().join("\n"));
   uk1104relay.lightsOffText->setPlainText(c->UK1104TurnOffLights().join("\n"));
   uk1104relay.usbOnText->setPlainText(c->UK1104TurnOnUSB().join("\n"));
   uk1104relay.usbOffText->setPlainText(c->UK1104TurnOffUSB().join("\n"));
   uk1104input.enableDigitalInputCheckBox->setChecked(c->UK1104PollInput());
   uk1104input.channelNumberSpinBox->setValue(c->UK1104InputChannel());
   uk1104input.channelValuePressed->
      setCurrentIndex(c->UK1104ButtonPressedValue());
   leftcam.vendorEdit->setText(c->LeftCameraVendor());
   leftcam.modelEdit->setText(c->LeftCameraModel());
   leftcam.serialEdit->setText(c->LeftCameraSerial());
   leftcam.srcDirectoryEdit->setText(c->LeftCameraSrcDirectory());
   leftcam.imageFilterEdit->setPlainText(c->LeftCameraImageFilters().join("\n"));
   rightcam.vendorEdit->setText(c->RightCameraVendor());
   rightcam.modelEdit->setText(c->RightCameraModel());
   rightcam.serialEdit->setText(c->RightCameraSerial());
   rightcam.srcDirectoryEdit->setText(c->RightCameraSrcDirectory());
   rightcam.imageFilterEdit->
      setPlainText(c->RightCameraImageFilters().join("\n"));
   destdir.destDirectoryEdit->setText(c->DestinationDirectory());
   destdir.leftSubdirEdit->setText(c->LeftCameraSubdir());
   destdir.rightSubdirEdit->setText(c->RightCameraSubdir());
   if (c->PreferenceIndependentButtons()) {
      prefs.independentRadio->setChecked(true);
   } else {
      prefs.togetherRadio->setChecked(true);
   }
   QSize pvs = c->PreferenceImagePreviewSize();
   if (pvs == QSize(640,480)) {
      prefs.previewSizeCombo->setCurrentIndex(0);
   } else if (pvs == QSize(320,240)) {
      prefs.previewSizeCombo->setCurrentIndex(1);
   }
   InitProgram(lights_prog.programTable, c->LightsProgram());
   InitProgram(cam_prog.programTable, c->CameraProgram());
   InitProgram(download_prog.programTable, c->DownloadProgram());
   download_prog.constSpinBox->setValue(c->DownloadConstTenthsOfSecond());
   download_prog.perImageSpinBox->setValue(c->DownloadOneImageTenthsOfSecond());

   // Now wait for user to hit OK or Cancel

   if (exec() == QDialog::Accepted) {

      // User hit OK - we need to copy all the data out of the GUI
      // fields and into the ConfigData instance.

      c->uk1104_vendor = uk1104id.vendorIdEdit->text();
      c->uk1104_model = uk1104id.modelIdEdit->text();
      c->uk1104_id_code = uk1104id.uk1104IdCodeEdit->text();
      c->uk1104_initialize = uk1104id.initCommandEdit->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->uk1104_turn_on_lights = uk1104relay.lightsOnText->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->uk1104_turn_off_lights = uk1104relay.lightsOffText->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->uk1104_turn_on_USB = uk1104relay.usbOnText->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->uk1104_turn_off_USB = uk1104relay.usbOffText->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->uk1104_poll_input = uk1104input.enableDigitalInputCheckBox->isChecked();
      c->uk1104_input_channel = uk1104input.channelNumberSpinBox->value();
      c->uk1104_button_pressed_value =
         uk1104input.channelValuePressed->currentIndex();
      c->left_camera_vendor = leftcam.vendorEdit->text();
      c->left_camera_model = leftcam.modelEdit->text();
      c->left_camera_serial = leftcam.serialEdit->text();
      c->left_camera_src_directory = leftcam.srcDirectoryEdit->text();
      c->left_camera_image_filters = leftcam.imageFilterEdit->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->right_camera_vendor = rightcam.vendorEdit->text();
      c->right_camera_model = rightcam.modelEdit->text();
      c->right_camera_serial = rightcam.serialEdit->text();
      c->right_camera_src_directory = rightcam.srcDirectoryEdit->text();
      c->right_camera_image_filters = rightcam.imageFilterEdit->
         toPlainText().split("\n", QString::SkipEmptyParts);
      c->destination_directory = destdir.destDirectoryEdit->text();
      c->left_camera_subdir = destdir.leftSubdirEdit->text();
      c->right_camera_subdir = destdir.rightSubdirEdit->text();
      c->preference_independent_buttons = prefs.independentRadio->isChecked();
      switch(prefs.previewSizeCombo->currentIndex()) {
      case 0:
         c->preference_image_preview_size = QSize(640,480);
         break;
      case 1:
         c->preference_image_preview_size = QSize(320,240);
         break;
      }
      UpdateProgram(lights_prog.programTable, c->lights_prog);
      UpdateProgram(cam_prog.programTable, c->cam_prog);
      UpdateProgram(download_prog.programTable, c->download_prog);
      c->download_const_tenths_of_seconds =
         download_prog.constSpinBox->value();
      c->download_one_image_tenths_of_seconds =
         download_prog.perImageSpinBox->value();

      // Now write the updated config info to disk.

      c->SaveConfigData();
   }
}

void
ConfigDialog::editProgramItem(
   int currentRow,
   int currentColumn,
   int previousRow,
   int previousColumn) {

   QTableWidget * tab = dynamic_cast<QTableWidget *>(sender());

   if ((previousColumn == 1) && (previousRow != -1)) {
      QComboBox * cb = dynamic_cast<QComboBox *>(
         tab->cellWidget(previousRow, previousColumn));
      if (cb != NULL) {
         QString act = cb->currentText();
         tab->removeCellWidget(previousRow, previousColumn);
         delete cb;
         curTab = NULL;
      }
   }
   if ((currentColumn == 1) && (currentRow != -1)) {
      tab->setCellWidget(currentRow, currentColumn,
         GetActionsCombo(currentRow, currentColumn, tab));
   }
}

void
ConfigDialog::maybeAddRow(QTableWidgetItem * item) {
   QTableWidget * tab = dynamic_cast<QTableWidget *>(sender());
   if ((tab->rowCount() - 1) == (item->row())) {
      tab->setRowCount(tab->rowCount() + 1);
   }
}

void
ConfigDialog::comboChanged(const QString& text) {
   QTableWidgetItem * item = curTab->item(curRow, curCol);
   if (item == NULL) {
      item = new QTableWidgetItem();
      curTab->setItem(curRow, curCol, item);
   }
   item->setText(text);
}

QComboBox *
ConfigDialog::GetActionsCombo(int newRow, int newCol, QTableWidget* newTab) {
   if (curTab != NULL) {
      QComboBox * cb = dynamic_cast<QComboBox *>(
         curTab->cellWidget(curRow, curCol));
      if (cb != NULL) {
         curTab->removeCellWidget(curRow, curCol);
         delete cb;
         curTab = NULL;
      }
   }
   QComboBox * actions_combo;
   QStringList actions;
   actions << tr("Turn on lights");
   actions << tr("Turn off lights");
   actions << tr("Turn on USB");
   actions << tr("Turn off USB");
   actions_combo = new QComboBox();
   actions_combo->addItems(actions);
   connect(actions_combo, SIGNAL(currentIndexChanged(const QString &)),
           this,          SLOT(comboChanged(const QString&)));
   curRow = newRow;
   curCol = newCol;
   curTab = newTab;
   comboChanged(actions.front());
   return actions_combo;
}

void
ConfigDialog::InitProgram(QTableWidget * tab, ProgramEntryList prog) {
   tab->clearContents();
   tab->setRowCount(prog.count() + 1);
   for (int i = 0; i < prog.count(); ++i) {
      tab->setItem(i, 0, new QTableWidgetItem(prog.at(i).timespec));
      tab->setItem(i, 1, new QTableWidgetItem(prog.at(i).actionspec));
   }
}

void
ConfigDialog::UpdateProgram(QTableWidget * tab, ProgramEntryList & prog) {
   prog.clear();
   for (int i = 0; i < tab->rowCount(); ++i) {
      QTableWidgetItem * time = tab->item(i, 0);
      QTableWidgetItem * action = tab->item(i, 1);
      ProgramEntry pe;
      if (time != NULL) {
         pe.timespec = time->text();
      }
      if (action != NULL) {
         pe.actionspec = action->text();
      }
      if (! (pe.timespec.isEmpty() && pe.actionspec.isEmpty())) {
         prog << pe;
      }
   }
}
