/*
        (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 Steet, 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 "globals.h"

#include <iostream>
#include <kstdaction.h>
#include <kaction.h>
#include <qlistbox.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qapplication.h>
#include <qtimer.h>
#include <qlabel.h>
#include <qaction.h>
#include <unistd.h>
#include <dirent.h>
#include <klocale.h>
#include <qstringlist.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <kaboutapplication.h>
#include <qcstring.h>
#include <kpassdlg.h>
#include <kmessagebox.h>
#include <ktempfile.h>
#include <kstandarddirs.h>
#include <kpassdlg.h>
#include <kdebug.h>
#include <qcheckbox.h>
#include <qspinbox.h>
#include <qpushbutton.h>
#include <kprocess.h>
#include <qdir.h>


KwlanMainWin::KwlanMainWin(QWidget* parent, const char* name, WFlags fl)
    : Kwlan(parent,name,fl)
{
}

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,FALSE);
    }

    return 0;
}

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



void KwlanMainWin::slotCheckInterfaces()
{
    QDir dir("/sys/class/net");
    QStringList list = dir.entryList(QDir::Dirs);
    if (list.isEmpty())
    {
        kdDebug() << "Coult not read /sys/class/net!" << endl;
        m_tray->show();
        return;
    }

    for ( QStringList::iterator it = list.begin(); it != list.end(); ++it )
    {
        if (!(((*it)==".") | ((*it)=="..")))
        {
            QString iface = (*it);
            QString typeFile = QString("/sys/class/net/");
            typeFile += iface;
            typeFile += QString("/type");
        // check if interface type is ethernet
            FILE* fp = fopen((typeFile).latin1(), "r");
            long retval = 0;
            if (fp)
            {
                fscanf(fp, "%lu", &retval);
                fclose(fp);
            }

            if (retval==1)
            {
                if (debugOutput) kdDebug() << "Checking interface "<<iface << endl;
                bool found = FALSE;
                KwlanInterface *it;
                for (it = m_interfaceList.first(); it ;it = m_interfaceList.next())
                {
                    if (it->getInterfaceName()==iface) found = TRUE;
                }
                if (!found)
                {
                    KwlanInterface *widget = new KwlanInterface(this);
                    widget->init(iface );
                    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->insertItem(iface);
                    cbInterface->setCurrentText(iface);
                    if (debugOutput) kdDebug() << "Added interface " << iface << endl;
                }
            }
        }
    }
    // Now check if we have any interfaces configured for monitoring
    bool showTrayWin = TRUE;
    KwlanInterface *iface;
    for (iface = m_interfaceList.first(); iface ;iface = m_interfaceList.next())
    {
        if (mainConfiguration().readMonitorInterface(iface->getInterfaceName()))
        {
            showTrayWin = FALSE;
        }
    }
    if (showTrayWin) m_tray->show();
    else m_tray->hide();

}


/*$SPECIALIZATION$*/
void KwlanMainWin::helpHandbook()
{
    kapp->invokeHelp();
}

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

void KwlanMainWin::profileActivate()
{
    QString iface = cbInterface->currentText();
    KwlanInterface *it;
    for (it = m_interfaceList.first();it; it=m_interfaceList.next())
    {
        if (it->getInterfaceName()== iface)
        {
            it->profileActivate( lbProfiles->currentText());
        }
    }

}

void KwlanMainWin::cbInterfaceChanged(const QString& iface)
{
    if (debugOutput) kdDebug() << "Selected interface has changed to "<<iface << endl;
    KwlanInterface *it;
    for (it = m_interfaceList.first();it; it=m_interfaceList.next())
    {
        if (it->getInterfaceName()== iface)
        {
            QStringList profiles = it->listProfiles();
            lbProfiles->clear();
            lbProfiles->insertStringList(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();
    KwlanInterface *it;
    for (it = m_interfaceList.first();it; it=m_interfaceList.next())
    {
        if (it->getInterfaceName()== iface)
        {
            it->slotScan();
        }
    }
}

void KwlanMainWin::profileDelete()
{
    QListBoxItem *selected = lbProfiles->selectedItem();
    // 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();
            KwlanInterface *it;
            for (it = m_interfaceList.first();it; it=m_interfaceList.next())
            {
                if (it->getInterfaceName()== iface)
                {
                    it->slotDeleteProfile( lbProfiles->currentText());
                    //lbProfiles->clear();
                    //lbProfiles->insertStringList(it->listProfiles());
                }
            }
        }
    }
}

void KwlanMainWin::profileModify()
{
    QString iface = cbInterface->currentText();
    QListBoxItem *selected = lbProfiles->selectedItem();
    // check if a profile is selected
    if (selected)
    {
        KwlanInterface *it;
        for (it = m_interfaceList.first();it; it=m_interfaceList.next())
        {
            if (it->getInterfaceName()== iface)
            {
                it->slotEditProfile( lbProfiles->currentText());
            }
        }

    }
}

void KwlanMainWin::profileNew()
{
        // Open Config Dialog
    QString iface = cbInterface->currentText();
    KwlanInterface *it;
    for (it = m_interfaceList.first();it; it=m_interfaceList.next())
    {
        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()
{
    QListBoxItem *selected = lbDialup->selectedItem();
    // 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("/") + lbDialup->currentText();
        KwlanSuProcess *proc = new KwlanSuProcess();
        *proc << "rm" << filename;
        proc->setDescription( i18n("delete dialup network"));
        updateDialupNetworks();
        proc->start();
    }
}

void KwlanMainWin::dialupModify()
{
    // get network
    QListBoxItem *selected = lbDialup->selectedItem();
    // check if a profile is selected
    if (!selected) {
        KMessageBox::sorry(this,i18n("No network selected!"));
        return;
    }
    
    QString sel(lbDialup->currentText());
    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
    QListBoxItem *selected = lbDialup->selectedItem();
    // check if a profile is selected
    if (!selected) {
        KMessageBox::sorry(this,i18n("No network selected!"));
        return;
    }
    
    QString sel(lbDialup->currentText());
    KDialup *tmpDial = new KDialup;
    tmpDial->disconnectNetwork(sel);
    delete tmpDial;
    

}

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

}


void KwlanMainWin::helpAbout()
{
    KAboutApplication about(this);
    about.exec();
}


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



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

void KwlanMainWin::updateProfiles()
{
    QString iface = cbInterface->currentText();
    KwlanInterface *it;
    for (it = m_interfaceList.first();it; it=m_interfaceList.next())
    {
        if (it->getInterfaceName()== iface)
        {
            lbProfiles->clear();
            lbProfiles->insertStringList(it->listProfiles());
        }
    }
}

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



void KwlanMainWin::slotInterfaceGone(KwlanInterface *iface)
{
    //if (debugOutput) 
      kdDebug() << "Lost interface " << iface->getInterfaceName() << endl;
    int id = m_interfaceList.find(iface);
    if (id!=-1)
        m_interfaceList.remove(id);
}

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

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

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

#include "kwlanmainwin.moc"





















