//-*-c++-*-
/***************************************************************************
 *   Copyright (C) 2003 by Fred Schaettgen                                 *
 *   kbluetoothd@schaettgen.de                                             *
 *                                                                         *
 *   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 "pindialog.h"
#include "pindefdialog.h"
#include "pingendialog.h"
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <kapplication.h>
#include <qlabel.h>
#include <stdlib.h>
#include <time.h>
#include <kmessagebox.h>
#include <libkbluetooth/hcisocket.h>
#include <libkbluetooth/deviceaddress.h>
#include <libkbluetooth/namerequest.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <kdebug.h>
#include <klocale.h>

PinDialog::PinDialog(QWidget* owner, bool /*bIncoming*/, 
    bool ownAuth, QString addr, QString devName) :
    KDialogBase(owner, "pinrequest", ownAuth, "Pin Request",
        ownAuth?(Close):(Ok|Cancel))
{
    bGotGenPin = false;
    this->bOwnAuth = ownAuth;
    this->addr = addr;
    hciSocket = NULL;
    QString name = devName;
    if (devName.length() == 0) {
        KBluetooth::NameRequest nameReq;
        name = nameReq.resolve(KBluetooth::DeviceAddress(addr));
    }
    if (bOwnAuth) {
        pinGenDlg = new PinGenerateDialog(this);
        connect(pinGenDlg->goButton, SIGNAL(clicked()),
            this, SLOT(slotGo()));
        connect(pinGenDlg->customPin, SIGNAL(toggled(bool)),
            this, SLOT(slotCustomPinToggled(bool)));
        pinGenDlg->messageLabel->setText(pinGenDlg->messageLabel->text()
            .arg(QString(name)).arg(QString(addr)));
        hciSocket = new KBluetooth::HciSocket(this);
        connect(hciSocket, SIGNAL(event(unsigned char, QByteArray)),
            this, SLOT(slotHciEvent(unsigned char, QByteArray)));
        hciSocket->open();
    }
    else {
        pinDlg = new PinDefaultDialog(this);
        pinDlg->messageLabel->setText(pinDlg->messageLabel->text()
            .arg(QString(name)).arg(QString(addr)));
        pinDlg->pinEdit->setFocus();
    }

    if (ownAuth) {
        setMainWidget(pinGenDlg);
        pinGenDlg->goButton->setFocus();
    }
    else {
        setMainWidget(pinDlg);
    }
}

PinDialog::~PinDialog()
{
}

QString PinDialog::getPin(bool bIn, bool ownAuth, QString addr, QString name)
{
    QGuardedPtr<PinDialog> dlg = new PinDialog(NULL, bIn, ownAuth, addr, name);
    if (ownAuth == true) {
        if (!dlg->pinGenDlg) return QString::null;
        dlg->show();
        while (dlg && dlg->pinGenDlg->isVisible() && dlg->bGotGenPin == false) {
            KApplication::kApplication()->processEvents(100);
        }
        // Don't delete the dialog immediately
        // Instead delete it when the user clicks 'close'
        if (dlg) {
            dlg->setWFlags(dlg->getWFlags() | Qt::WDestructiveClose);
        }
        if (dlg && dlg->bGotGenPin == true) {
            return dlg->pinGenDlg->pinEdit->text();
        }
        else {
            return QString::null;
        }
    }
    else {
        if (!dlg->pinDlg) return QString::null;
        QString ret;
        if (dlg->exec() == QDialog::Accepted) {
            ret = dlg->pinDlg->pinEdit->text();
        }
        else {
            ret = QString::null;
        }
        delete dlg;
        return ret;
    }
}


void PinDialog::slotCustomPinToggled(bool bOn)
{
    if (!pinGenDlg) return;
    if (bOn) {
        pinGenDlg->pinEdit->setReadOnly(false);
        pinGenDlg->pinEdit->setEnabled(true);
        pinGenDlg->pinEdit->setFocus();
    }
    else {
        pinGenDlg->pinEdit->setReadOnly(true);
        pinGenDlg->pinEdit->setEnabled(false);
        pinGenDlg->pinEdit->setText("");
    }
}

void PinDialog::slotGo()
{
    if (pinGenDlg) {
        if (pinGenDlg->customPin->isChecked() == false) {
            QString pin;
            ::srand(uint(::time(NULL)));
            for (int n=0; n<8; ++n) {
                pin += QString::number(rand() % 10);
            }
            pinGenDlg->pinEdit->setText(pin);
        }
        pinGenDlg->pinEdit->setReadOnly(true);
        pinGenDlg->pinEdit->setEnabled(true);
        pinGenDlg->customPin->setEnabled(false);
        pinGenDlg->goButton->setEnabled(false);
        bGotGenPin = true;
    }
}

void PinDialog::slotHciEvent(unsigned char eventCode, QByteArray buf)
{
    //const unsigned char *data = (unsigned char*)buf.data();
    if (eventCode == 0x06 /* authentication complete */)
    {
        kdDebug() << "PinDialog: authentication complete" << endl;
        
        unsigned char errorCode = buf[0];
        if (errorCode == 0) {
            KMessageBox::information(this,
                i18n("Pairing was sucessful."), i18n("Bluetooth PIN Server"), 
                    "pairing_successful_msgbox");
        }
        else {
            KMessageBox::detailedSorry(this,
                i18n("Pairing failed."), i18n("The devices could not be paired. \
The reported HCI error code is 0x%1.").arg(errorCode, 0, 16), i18n("Bluetooth PIN Server"));
        }
        
        deleteLater();
    }
}


#include "pindialog.moc"
