/*
        (c) 2006 by Thomas Michel <tom.michel@arcor.de>

        Kwlan is free software; you can redistribute it and/or modify
        it under the terms of the GNU Library General Public License as
        published by the Free Software Foundation; either version 2 of
        the License, or (at your option) any later version.

        Kwlan 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 Library General Public License for more details.

        You should have received a copy of the GNU Library General Public License
        along with this library; see the file COPYING.LIB.  If not, write to
        the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
        Boston, MA 02110-1301, USA.
*/


#include "kwlanmainwin.h"
#include "wlanlib.h"
#include "kprofileconfigdlg.h"
#include "kstartsupplicantdlg.h"
#include "wpa_ctrl.h"
#include "keventhistorydlg.h"
#include "kscandlg.h"
#include "kuserdatarequestdlg.h"
#include "kwlansettingsdlg.h"
#include "kwlansuprocess.h"
#include "kwlaninterface.h"
#include "dialup.h"
#include "kdialup.h"
#include "kdialupconfigdlg.h"
#include "kwlanmaintraywin.h"
#include "configuration.h"
#include "kwlanmainsettingsdlg.h"
#include "kaboutapplicationdialog.h"
#include "globals.h"

#include <iostream>
#include <kstandardaction.h>
#include <kaction.h>
#include <QListWidget>
#include <QTimer>
#include <unistd.h>
#include <dirent.h>
#include <klocale.h>
#include <QStringList>
#include <QFile>
#include <k3aboutapplication.h>
#include <kpassworddialog.h>
#include <kmessagebox.h>
#include <ktemporaryfile.h>
#include <kstandarddirs.h>
#include <kpassworddialog.h>
#include <kdebug.h>
#include <QCheckBox>
#include <QPushButton>
#include <k3process.h>
#include <QDir>
#include <ktoolinvocation.h>
#include <QCloseEvent>

//solid specific includes
#include <solid/deviceinterface.h>
#include <solid/networking.h>
#include <solid/device.h>
#include <solid/networkinterface.h>

KwlanMainWin::KwlanMainWin(QWidget* parent, const char* name, Qt::WFlags fl)
    : QMainWindow(parent,fl)//Kwlan(parent,name,fl)
{
    Kwlan::setupUi(this);
}

int KwlanMainWin::init() 
{
    // check for dialup user
    if (!::dialupUser)
    {
        tabDialup->setEnabled(FALSE);
    }
    if (!mainConfiguration().readStartMinimized())
        show();
    // now update Dialup Networks
    updateDialupNetworks();
    m_tray = new KwlanMainTrayWin( this, "Kwlan" );
    //m_tray->show();
    connect (m_tray, SIGNAL( quitSelected() ), this, SLOT( fileExit() ) );
    connect (m_tray, SIGNAL (aboutSelected() ),this, SLOT(helpAbout()));
    connect (m_tray, SIGNAL(sigMonitorInterface(QString, bool)), this, SLOT(slotHandleMonitorInterface(QString,bool)));
    connect (m_tray, SIGNAL(sigConfigureInterface(QString, bool)), this, SLOT(slotHandleConfigureInterface(QString,bool)));
    slotCheckInterfaces();
    m_timer = new QTimer(this);
    if (m_timer){
        connect (m_timer, SIGNAL(timeout()),SLOT(slotCheckInterfaces()));
        m_timer->start(5000);
    }

    return 0;
}

KwlanMainWin::~KwlanMainWin()
{
    if (m_timer)
        delete m_timer;
    //m_configuration->writeSettings();
}



void KwlanMainWin::slotCheckInterfaces()
{
    
    //get a Network Device
    QList<Solid::Device> netlist = Solid::Device::listFromType(Solid::DeviceInterface::NetworkInterface, QString());
    
    //check to see if no network devices were found
    if(netlist.empty())
    {
        kDebug() << "No network devices found!" << endl;
        return;
    }
    
    foreach( Solid::Device  device, netlist )
    {
        Solid::NetworkInterface *netdev= device.as<Solid::NetworkInterface>();
        //keep the program from crashing in the event that there's a bug in solid
        if(!netdev)
        {
            kDebug() << "Device could not be converted.  There is a bug." << endl;
            return;
        }
        if (::debugOutput) kDebug() << "The iface of " << device.udi() << " is " << netdev->ifaceName();
        QString iface = netdev->ifaceName();          
        if (debugOutput) kDebug() << "Checking interface "<<iface;
        bool found = FALSE;
        interfaceList::iterator it;
        for (it = m_interfaceList.begin(); it!=m_interfaceList.end() ;it++)
        {
            if ((*it)->getInterfaceName()==iface) found = TRUE;
        }
        if (!found)
        {
                
            KwlanInterface *widget = new KwlanInterface(this);
            widget->init(iface,&device );
            //widget->setSolidDevice(netdev);
            connect (widget, SIGNAL(interfaceGone(KwlanInterface*)), this, SLOT(slotInterfaceGone(KwlanInterface*)));
            connect (widget, SIGNAL(networksChanged()), this, SLOT(updateProfiles()));
            KwlanTrayWin *trayWin = new KwlanTrayWin(this,"Kwlan");
            trayWin->setInterface(widget);
            trayWin->setInterfaceName(iface);
            connect(trayWin, SIGNAL( quitSelected() ), this, SLOT( fileExit() ) );
            connect(trayWin, SIGNAL (aboutSelected()),this,SLOT(helpAbout()));
            connect (trayWin, SIGNAL (sigTrayWinClicked(QString)), this, SLOT(slotChangeInterface( QString)));
            connect (trayWin, SIGNAL(sigMonitorInterface(QString, bool)), this, SLOT(slotHandleMonitorInterface(QString,bool)));
            connect (trayWin, SIGNAL(sigConfigureInterface(QString, bool)), this, SLOT(slotHandleConfigureInterface(QString,bool)));
            connect (this, SIGNAL(sigConfigureInterface(QString, bool)), widget, SLOT(slotEnableConfigureInterface(QString,bool)));
            connect (this, SIGNAL(sigMonitorInterface(QString, bool)), trayWin, SLOT(slotShowTrayWin(QString,bool)));
            if (mainConfiguration().readMonitorInterface(iface)) trayWin->show();
                
                
            m_interfaces.append(iface);
            m_interfaceList.append(widget);
            cbInterface->addItem(iface);
            cbInterface->setCurrentIndex(cbInterface->findText(iface));
            if (debugOutput) kDebug() << "Added interface " << iface;
        }
    }
    // Now check if we have any interfaces configured for monitoring
    bool showTrayWin = TRUE;
    interfaceList::iterator iface;
    for (iface = m_interfaceList.begin(); iface !=m_interfaceList.end() ;iface++)
    {
        if (mainConfiguration().readMonitorInterface((*iface)->getInterfaceName()))
        {
            showTrayWin = FALSE;
        }
    }
    if (showTrayWin) m_tray->show();
    else m_tray->hide();
}


/*$SPECIALIZATION$*/
void KwlanMainWin::helpHandbook()
{
    KToolInvocation::invokeHelp();
}

void KwlanMainWin::fileSettings()
{
    KwlanMainSettingsDlg *settings = new KwlanMainSettingsDlg();
    if (!settings) return;
    settings->show();
    settings->exec();
}

void KwlanMainWin::profileActivate()
{
    QString iface = cbInterface->currentText();
    interfaceList::iterator it;
    for (it = m_interfaceList.begin();it!=m_interfaceList.end(); it++)
    {
        if ((*it)->getInterfaceName()== iface)
        {
            QListWidgetItem *sel = lbProfiles->currentItem();
            if (sel != 0)
                (*it)->profileActivate( sel->text());
        }
    }

}

void KwlanMainWin::cbInterfaceChanged(const QString& iface)
{
    if (debugOutput) kDebug() << "Selected interface has changed to "<<iface;
    interfaceList::iterator it;
    for (it = m_interfaceList.begin();it != m_interfaceList.end(); it++)
    {
        if ((*it)->getInterfaceName()== iface)
        {
            QStringList profiles = (*it)->listProfiles();
            lbProfiles->clear();
            lbProfiles->addItems(profiles);
            bool configure = (*it)->getConfigureInterface();
            pbActivate->setEnabled(configure);
            pbDelete->setEnabled(configure);
            pbModify->setEnabled(configure);
            pbNew->setEnabled(configure);
            pbScan->setEnabled(configure && (*it)->getInterfaceData().wirelessDevice);
        }
    }
}

void KwlanMainWin::scan()
{
    QString iface = cbInterface->currentText();
    interfaceList::iterator it;
    for (it = m_interfaceList.begin();it != m_interfaceList.end(); it++)
    {
        if ((*it)->getInterfaceName()== iface)
        {
            (*it)->slotScan();
        }
    }
}

void KwlanMainWin::profileDelete()
{
    QListWidgetItem *selected = lbProfiles->currentItem();
    // check if a profile is selected
    if (selected)
    {
        int answer = KMessageBox::warningYesNo(this,i18n("Do you really want to delete this profile?"));
        if (answer==KMessageBox::Yes){
            QString iface = cbInterface->currentText();
            interfaceList::iterator it;
            for (it = m_interfaceList.begin();it != m_interfaceList.end(); it++)
            {
                if ((*it)->getInterfaceName()== iface)
                {
                    (*it)->slotDeleteProfile( selected->text());
                    //lbProfiles->clear();
                    //lbProfiles->insertStringList(it->listProfiles());
                }
            }
        }
    }
}

void KwlanMainWin::profileModify()
{
    QString iface = cbInterface->currentText();
    QListWidgetItem *selected = lbProfiles->currentItem();
    // check if a profile is selected
    if (selected)
    {
        interfaceList::iterator it;
        for (it = m_interfaceList.begin();it != m_interfaceList.end(); it++)
        {
            if ((*it)->getInterfaceName()== iface)
            {
                (*it)->slotEditProfile( selected->text());
            }
        }

    }
}

void KwlanMainWin::profileNew()
{
        // Open Config Dialog
    QString iface = cbInterface->currentText();
    interfaceList::iterator it;
    for (it = m_interfaceList.begin();it != m_interfaceList.end(); it++)
    {
        if ((*it)->getInterfaceName()== iface)
        {
            KProfileConfigDlg *profileDlg = new KProfileConfigDlg();
            if (!profileDlg) return;
            profileDlg->setInterface( (*it));
            profileDlg->newNetwork();
            profileDlg->show();
            profileDlg->exec();
            //cbInterfaceChanged(iface);
            return;
        }
    }
}

void KwlanMainWin::dialupNew()
{
    KDialupConfigDlg *conf = new KDialupConfigDlg();
    connect (conf, SIGNAL(dialupNetworksUpdated()),this, SLOT(updateDialupNetworks()));
    conf->show();
}

void KwlanMainWin::dialupDelete()
{
    QListWidgetItem *selected = lbDialup->currentItem();
    // check if a profile is selected
    if (!selected) {
        KMessageBox::sorry(this,i18n("No network selected."));
        return;
    }
    int answer = KMessageBox::warningYesNo(this,i18n("Do you really want to delete this profile?"));
    if (answer==KMessageBox::Yes){
        QString filename = QString(PPP_PEERS) + QString("/") + selected->text();
        KwlanSuProcess *proc = new KwlanSuProcess();
        *proc << "rm" << filename;
        proc->setDescription( i18n("delete dialup network"));
        updateDialupNetworks();
        proc->start();
    }
}

void KwlanMainWin::dialupModify()
{
    // get network
    QListWidgetItem *selected = lbDialup->currentItem();
    // check if a profile is selected
    if (!selected) {
        KMessageBox::sorry(this,i18n("No network selected."));
        return;
    }
    
    QString sel(selected->text());
    KDialupConfigDlg *conf = new KDialupConfigDlg();
    connect (conf, SIGNAL(dialupNetworksUpdated()),this, SLOT(updateDialupNetworks()));
    if (conf->init(sel))
        conf->show();
        else delete conf;
}

void KwlanMainWin::dialupDisconnect()
{
    // get network
    QListWidgetItem *selected = lbDialup->currentItem();
    // check if a profile is selected
    if (!selected) {
        KMessageBox::sorry(this,i18n("No network selected."));
        return;
    }
    
    QString sel(selected->text());
    KDialup *tmpDial = new KDialup;
    tmpDial->disconnectNetwork(sel);
    delete tmpDial;
    

}

void KwlanMainWin::dialupConnect()
{
    // get network
    QListWidgetItem *selected = lbDialup->currentItem();
    // check if a profile is selected
    if (!selected) {
        KMessageBox::sorry(this,i18n("No network selected."));
        return;
    }
    KDialup *dialup = new KDialup();
    QString sel(selected->text());
    dialup->connectNetwork(sel);

}


void KwlanMainWin::helpAbout()
{
    KAboutApplicationDialog aboutdlg(&::about,(QWidget *)this);
    aboutdlg.exec();
}


void KwlanMainWin::fileExit()
{
    //m_configuration->writeSettings();
    kDebug() << "Exiting...";
    kapp->quit();
}



void KwlanMainWin::updateDialupNetworks()
{
    QStringList networks = listDialupNetworks();
    lbDialup->clear();
    for (QStringList::iterator it = networks.begin();it != networks.end();it++)
    {
        lbDialup->addItem(*it);
    }
}

void KwlanMainWin::updateProfiles()
{
    QString iface = cbInterface->currentText();
    interfaceList::iterator it;
    for (it = m_interfaceList.begin(); it!=m_interfaceList.end() ;it++)
    {
        if ((*it)->getInterfaceName()== iface)
        {
            lbProfiles->clear();
            lbProfiles->addItems((*it)->listProfiles());
        }
    }
}

void KwlanMainWin::close()
{
    QWidget::close();
}



void KwlanMainWin::slotInterfaceGone(KwlanInterface *iface)
{
    //if (debugOutput) 
    kDebug() << "Lost interface " << iface->getInterfaceName();
    bool found = FALSE;
    interfaceList::iterator it; 
    for (it = m_interfaceList.begin(); it != m_interfaceList.end();it++)
    {
        if (*it == iface)
            it = m_interfaceList.erase(it);
    }
}

void KwlanMainWin::slotChangeInterface( QString iface)
{
    cbInterface->setCurrentIndex(cbInterface->findText(iface));
}

void KwlanMainWin::slotHandleMonitorInterface(QString iface, bool monitor)
{
    emit sigMonitorInterface(iface, monitor);
}

void KwlanMainWin::slotHandleConfigureInterface(QString iface, bool configure)
{
    emit sigConfigureInterface(iface, configure);
}

void KwlanMainWin::closeEvent(QCloseEvent *event)
{
    kDebug() << "Close Event";
    event->ignore();
    hide();
}

#include "kwlanmainwin.moc"

