/***************************************************************************
 *   Copyright (C) 2003 by Mattia Merzi                                    *
 *   ottobit@ferrara.linux.it                                              *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/

#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <kdebug.h>
// #include <libkbluetooth/inquiry.h>

using namespace KBluetooth;

#define DEV_ID 0

void KBlueLockConfig::pushbutton_add_clicked() {
  int i = listbox_devices_found->currentItem();
  if (i != -1) {
    kdDebug() << "**********************" << endl;
    kdDebug() << "pushbutton_add_clicked says: " << endl;
    kdDebug() << "sizes: " << scan_addrs->size() << " - ";
    kdDebug() << scan_names->size() << " - ";
    kdDebug() << scan_types->size() << " - " << endl;
    kdDebug() << "bdaddr: " << (*scan_addrs)[i] << endl;
    kdDebug() << "name:   " << (*scan_names)[i] << endl;
    kdDebug() << "type:   " << (*scan_types)[i] << endl;
    kdDebug() << "**********************" << endl;
    if (config->addDevice((*scan_addrs)[i],(*scan_names)[i],(*scan_types)[i])) {
      QString* tmp = new QString();
      tmp->append((*scan_addrs)[i]).append(":").append((*scan_names)[i]);
      listbox_trusted_devices->insertItem(*tmp);
    } else {
      QMessageBox::critical(this,"Error !",
        "The item you are trying to add is already present in the\n"
        "trusted devices list. Try removing it first.\n\nThank you.");
    }
  }
}

void KBlueLockConfig::pushbutton_add_all_clicked() {
  unsigned int i; // this should be size_type (or size_t) ...
  for (i=0;i<(scan_addrs->size());i++) {
    if (config->addDevice((*scan_addrs)[i],(*scan_names)[i],(*scan_types)[i])) {
      QString* tmp = new QString();
      tmp->append((*scan_addrs)[i]).append(":").append((*scan_names)[i]);
      listbox_trusted_devices->insertItem(*tmp);
    }
  }
}

void KBlueLockConfig::pushbutton_trash_clicked() {
  int i = listbox_trusted_devices->currentItem();
  if (i != -1) {
    if (config->removeDevice(i)) {
      listbox_trusted_devices->removeItem(i);
    } else {
      QMessageBox::critical(this,"Too bad, guy ...",
        "You've found a bug ...\nPlease report to the author (ottobit@ferrara.linux.it)"
        "\n\nThank you.");
    }
  }
}

void KBlueLockConfig::pushbutton_exit_clicked() {
  kdDebug() << "config->isChanged() ? " << config->isChanged() << endl;
  if (!config->isChanged()) {
    quit();
  } else {
       switch( QMessageBox::information( this, "Application name here",
               "Configuration has been changed\n\n"
               "Do you want to save the changes before exiting?",
               "&Save", "&Discard", "Cancel",
               0,      // Enter == button 0
               2 ) ) { // Escape == button 2
           case 0: // Save clicked or Alt+S pressed or Enter pressed.
               // save
               this->save_changes();
           case 1: // Discard clicked or Alt+D pressed
               // don’t save but exit
               this->quit();
               break;
           case 2: // Cancel clicked or Alt+C pressed or Escape pressed
               // don’t exit
               break;
       }
  }
}

void KBlueLockConfig::pushbutton_save_clicked() {
  save_changes();
}

void KBlueLockConfig::pushbutton_test_clicked() {
  QMessageBox::information(this,"sorry ...","Not implemented yet !");
}

void KBlueLockConfig::pushbutton_default_screenlock_clicked() {
  KProcess* proc = new KProcess();
  QApplication::connect(proc, SIGNAL(processExited(KProcess *)),this,
    SLOT(slotSetDefaultLockProcessExited(KProcess*)));

  if (getuid() != 0) {
    QString kdesu;
    QString path = getenv("PATH");
    path.append(":/usr/bin");
    kdesu = KGlobal::dirs()->findExe("kdesu", path);
    *proc << kdesu;
  }
  *proc << "/bin/sh" << "setdefaultlock.sh";
  if (proc->start()) proc_ok=true;
  else QMessageBox::critical(this,"Error !",
    "Error starting /bin/sh. Possible causes are:\n"
    " - The process is already running.\n"
    " - The starting of the process failed (could not fork).\n"
    " - The executable was not found.\n");
}

void KBlueLockConfig::slotSetDefaultLockProcessExited(KProcess* proc) {
  kdDebug() << "process exited !!!" << endl;
  if (proc->normalExit()) {
    kdDebug() << "normal exit" << endl;
    QString str = "setdefaultlock.sh returned error code:\n";
    int status = proc->exitStatus();
    switch (status) {
     case 0: str+="0: ok."; break;
     case 1: str+="1: already installed as default lock."; break;
     case 2: str+="2: cannot find kdesktop_lock."; break;
     case 3: str+="3: kbluelock was not found where kdesktop_lock is."; break;
     case 4: str+="4: error ranaming kdesktop_lock."; break;
     case 5: str+="5: error renaming kbluelock."; break;
     default: str+="unknown error";
    }
    kdDebug() << str.ascii() << endl;
    if (status!=0) QMessageBox::critical(this,"Error !",str);
  } else {
    QMessageBox::critical(this,"Error !","Process Killed");
  }
}

void KBlueLockConfig::slotInquiryDeviceFound(const KBluetooth::DeviceAddress& addr) {
  kdDebug() << "SLOT: found device: " << QString(addr) << endl;
  scan_addrs->append(QString(addr).ascii());
  scan_names->append("_");
  scan_types->append("_");
  listbox_devices_found->insertItem(QString(addr).ascii());
}

void KBlueLockConfig::slotInquiryFinnished() {
  kdDebug() << "SLOT: inquiry finished." << endl;
  QApplication::restoreOverrideCursor();
  scanning = false;
}

void KBlueLockConfig::pushbutton_scan_clicked() {
  if (!scanning) {
    scanning = true;
    QApplication::setOverrideCursor(WaitCursor);
    listbox_devices_found->clear();
    scan_addrs->clear();
    scan_names->clear();
    scan_types->clear();
    inquiry->inquiry();
  }
}

void KBlueLockConfig::pushbutton_query_clicked() {
 if (!scanning) {
  NameRequest nameRequest;

  listbox_devices_found->clear();
  scan_names->clear();
  scan_types->clear();

  QString tmp;
  QStringList::Iterator it_a = scan_addrs->begin();
  while ( it_a != scan_addrs->end() ) {
    tmp = nameRequest.resolve(DeviceAddress(*it_a));
    if (tmp != QString::null) {
      scan_names->append(tmp);
      scan_types->append("_");
      tmp.prepend(":").prepend(*it_a);
      listbox_devices_found->insertItem(tmp);
    } else {
      listbox_devices_found->clear();
      scan_addrs->clear();
      scan_names->clear();
      scan_types->clear();
      tmp = QString("Name request failed. Error message is: ");
      tmp.append(nameRequest.lastErrorMessage());
      QMessageBox::critical(this,"Error !",tmp);
      return;
    }
    it_a++;
  }
 }
}

void KBlueLockConfig::check_validate_name_toggled( bool on ) {
  config->setValidateName(on);
}

void KBlueLockConfig::check_validate_bdaddr_toggled( bool on ) {
  config->setValidateBDADDR(on);
}

void KBlueLockConfig::check_validate_device_type_toggled( bool on ) {
  config->setValidateDeviceType(on);
  QMessageBox::information(this,"sorry ...","Not implemented yet !");
}

void KBlueLockConfig::spin_interval_value_changed( int _val ) {
  kdDebug() << "spin_interval says: " << _val << endl;
  if (_val != old_spin_interval_value) {
    kdDebug() << "spin_interval says: changed ! :)" << endl;
    config->setScanInterval(_val);
    if (_val == 0) {
      radiobutton_continuous->setChecked(true);
    } else {
      radiobutton_timed->setChecked(true);
    }
  }
  old_spin_interval_value = _val;
}

void KBlueLockConfig::radiobutton_timed_toggled( bool on ) {
  kdDebug() << "radiobutton_timed says: " << on << endl;
}

void KBlueLockConfig::radiobutton_continuous_toggled( bool on ) {
  kdDebug() << "radiobutton_continuous says: " << on << endl;
  if (on == true) {
    spin_interval_value_changed(0);
    spin_interval->setValue(0);
  }
}
