/* This file is part of KNemo
   Copyright (C) 2004, 2005 Percy Leonhardt <percy@eris23.de>

   KNemo 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.

   KNemo 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 <unistd.h>

#include <tqpixmap.h>

#include <kdebug.h>
#include <tdeglobal.h>
#include <tdelocale.h>
#include <kprocess.h>
#include <tdepopupmenu.h>
#include <kiconloader.h>
#include <knotifyclient.h>

#include "data.h"
#include "interface.h"
#include "knemodaemon.h"
#include "interfaceicon.h"
#include "interfacetray.h"
#include "interfacemonitor.h"
#include "interfacetooltip.h"

const TQString InterfaceIcon::ICON_DISCONNECTED = "network_disconnected";
const TQString InterfaceIcon::ICON_CONNECTED = "network_connected";
const TQString InterfaceIcon::ICON_INCOMING = "network_incoming";
const TQString InterfaceIcon::ICON_OUTGOING = "network_outgoing";
const TQString InterfaceIcon::ICON_TRAFFIC = "network_traffic";
const TQString InterfaceIcon::SUFFIX_PPP = "_ppp";
const TQString InterfaceIcon::SUFFIX_LAN = "_lan";
const TQString InterfaceIcon::SUFFIX_WLAN = "_wlan";

InterfaceIcon::InterfaceIcon( Interface* interface )
    : TQObject(),
      mInterface( interface ),
      mTray( 0L )
{
}

InterfaceIcon::~InterfaceIcon()
{
    if ( mTray != 0L )
        delete mTray;
}

void InterfaceIcon::updateStatus( int status )
{
    if ( mTray == 0L )
        return;

    // If the user wants something different than the default icons
    // append the correct suffix to the filename.
    TQString suffix;
    if ( mInterface->getSettings().iconSet == Interface::NETWORK )
    {
        suffix = SUFFIX_LAN;
    }
    else if ( mInterface->getSettings().iconSet == Interface::WIRELESS )
    {
        suffix = SUFFIX_WLAN;
    }
    else if ( mInterface->getSettings().iconSet == Interface::MODEM )
    {
        suffix = SUFFIX_PPP;
    }
    else
    {
        suffix = ""; // use standard icons
    }

    // Now set the correct icon depending on the status of the interface.
    if ( status == Interface::NOT_AVAILABLE ||
         status == Interface::NOT_EXISTING )
    {
        mTray->setPixmap( mTray->isShown() ? mTray->loadSizedIcon( ICON_DISCONNECTED + suffix, mTray->width() ) : mTray->loadIcon( ICON_DISCONNECTED + suffix ) );
    }
    else if ( ( status & Interface::RX_TRAFFIC ) &&
              ( status & Interface::TX_TRAFFIC ) )
    {
        mTray->setPixmap( mTray->isShown() ? mTray->loadSizedIcon( ICON_TRAFFIC + suffix, mTray->width() ) : mTray->loadIcon( ICON_TRAFFIC + suffix ) );
    }
    else if ( status & Interface::RX_TRAFFIC )
    {
        mTray->setPixmap( mTray->isShown() ? mTray->loadSizedIcon( ICON_INCOMING + suffix, mTray->width() ) : mTray->loadIcon( ICON_INCOMING + suffix ) );
    }
    else if ( status & Interface::TX_TRAFFIC )
    {
        mTray->setPixmap( mTray->isShown() ? mTray->loadSizedIcon( ICON_OUTGOING + suffix, mTray->width() ) : mTray->loadIcon( ICON_OUTGOING + suffix ) );
    }
    else
    {
        mTray->setPixmap( mTray->isShown() ? mTray->loadSizedIcon( ICON_CONNECTED + suffix, mTray->width() ) : mTray->loadIcon( ICON_CONNECTED + suffix ) );
    }
}

void InterfaceIcon::updateToolTip()
{
    if ( mTray == 0L )
        return;

    TQString toolTip = mInterface->getSettings().alias;
    if ( toolTip == TQString() )
        toolTip = mInterface->getName();
    new InterfaceToolTip( mInterface,  mTray );
}

void InterfaceIcon::updateMenu()
{
    if ( mTray == 0L )
        return;

    // Remove all old entries.
    TDEPopupMenu* menu = mTray->contextMenu();
    int count = menu->count();
    for ( int i = 0; i < count - 6; i++ )
        menu->removeItemAt( 6 );

    InterfaceSettings& settings = mInterface->getSettings();

    // If the user wants statistics, add an entry to show them.
    if ( settings.activateStatistics )
    {
        menu->insertItem( i18n( "Open &Statistics" ), this,
                          TQ_SIGNAL( statisticsSelected() ) );
    }

    // If the user wants custom commands, add them.
    if ( settings.customCommands )
    {
        menu->insertSeparator();
        TQValueVector<InterfaceCommand>::iterator it;
        for ( it = settings.commands.begin(); it != settings.commands.end(); it++ )
            (*it).id = menu->insertItem( (*it).menuText );
    }
}

void InterfaceIcon::resizeIcon()
{
    updateTrayStatus(0, false);
}

void InterfaceIcon::updateTrayStatus( int previousState, bool notify )
{
    bool interfaceExists = mInterface->getData().existing;
    bool interfaceAvailable = mInterface->getData().available;
    bool hideWhenNotExisting = mInterface->getSettings().hideWhenNotExisting;
    bool hideWhenNotAvailable = mInterface->getSettings().hideWhenNotAvailable;

    // notification 'interface not available'
    if ( !interfaceAvailable && mTray != 0L &&
         previousState == Interface::AVAILABLE && notify )
    {
        /* When KNemo is starting we don't show the change in connection
         * status as this would be annoying when KDE starts.
         */
        TQString title;
        if ( mInterface->getSettings().alias != TQString() )
            title = mInterface->getSettings().alias;
        else
            title = mInterface->getName();

        KNotifyClient::event( mTray->winId(), "knemo_disconnected",
                              title + ":\n" + i18n( "Not connected." ) );
        /* Wait half a second before deleting the tray so that the call
         * to the notification daemon has a chance to run before the
         * winId gets invalid.
         */
        usleep( 500000 );
    }

    // notification 'interface not existing'
    if ( !interfaceExists && mTray != 0L &&
         previousState != Interface::UNKNOWN_STATE && notify )
    {
        /* When KNemo is starting we don't show the change in connection
         * status as this would be annoying when KDE starts.
         */
        TQString title;
        if ( mInterface->getSettings().alias != TQString() )
            title = mInterface->getSettings().alias;
        else
            title = mInterface->getName();

        KNotifyClient::event( mTray->winId(), "knemo_notexisting",
                              title + ":\n" + i18n( "Not existing." ) );
        /* Wait half a second before deleting the tray so that the call
         * to the notification daemon has a chance to run before the
         * winId gets invalid.
         */
        usleep( 500000 );
    }

    /* Remove the icon if
     * - the interface is not available and the option to hide it is selected
     * - the interface does not exist, the option to hide it is selected
     *   and the other option is not selected
     */
    if ( mTray != 0L &&
         ( ( !interfaceAvailable && hideWhenNotAvailable ) ||
           ( !interfaceExists && hideWhenNotExisting && !hideWhenNotAvailable ) ) )
    {
        delete mTray;
        mTray = 0L;
    }
    /* Create the icon if
     * - the interface is available
     * - the interface is not available and the option to hide it is not
     *   selected and the interface does exist
     * - the interface does not exist and the option to hide it is not selected
     *   and the other option is not selected
     */
    else if ( mTray == 0L &&
              ( interfaceAvailable ||
                ( !interfaceAvailable && !hideWhenNotAvailable && interfaceExists ) ||
                ( !interfaceExists && !hideWhenNotExisting && !hideWhenNotAvailable ) ) )
    {
        mTray = new InterfaceTray( mInterface->getName() );
        TQToolTip::add( mTray, mInterface->getName() );
        TDEPopupMenu* menu = mTray->contextMenu();
        connect( menu, TQ_SIGNAL( activated( int ) ),
                 this, TQ_SLOT( menuActivated( int ) ) );
        connect( mTray, TQ_SIGNAL( leftClicked() ),
                 mInterface, TQ_SLOT( showStatusDialog() ) );
        connect( mTray, TQ_SIGNAL( graphSelected( bool ) ),
                 mInterface, TQ_SLOT( showSignalPlotter( bool ) ) );
        connect( mTray, TQ_SIGNAL( configSelected() ),
                 this, TQ_SLOT( showConfigDialog() ) );
        connect( mTray, TQ_SIGNAL( iconResized() ),
                 this, TQ_SLOT( resizeIcon() ) );

        updateStatus( mInterface->getState() );
        updateToolTip();
        updateMenu();
        mTray->show();
    }

    // notification 'interface available'
    if ( interfaceAvailable && mTray != 0L &&
         previousState != Interface::UNKNOWN_STATE && notify )
    {
        /* When KNemo is starting we don't show the change in connection
         * status as this would be annoying when KDE starts.
         */
        TQString title;
        if ( mInterface->getSettings().alias != TQString() )
            title = mInterface->getSettings().alias;
        else
            title = mInterface->getName();

        /* Wait half a second before calling the notification daemon
         * so that the winId of the tray is valid when used below.
         */
        usleep( 500000 );
        if ( mInterface->getData().wirelessDevice )
        {
            KNotifyClient::event( mTray->winId(), "knemo_connected",
                                  title + ":\n" + i18n( "Connection established to\n" ) +
                                  mInterface->getWirelessData().essid );
        }
        else
        {
            KNotifyClient::event( mTray->winId(), "knemo_connected",
                                  title + ":\n" + i18n( "Connection established." ) );
        }
    }
}

void InterfaceIcon::showConfigDialog()
{
    KNemoDaemon::sSelectedInterface = mInterface->getName();

    TDEProcess process;
    process << "tdecmshell" << "kcm_knemo";
    process.start( TDEProcess::DontCare );
}

void InterfaceIcon::menuActivated( int id )
{
    InterfaceSettings& settings = mInterface->getSettings();
    TQValueVector<InterfaceCommand>::iterator it;
    for ( it = settings.commands.begin(); it != settings.commands.end(); it++ )
    {
        if ( (*it).id == id )
        {
            TDEProcess process;
            if ( (*it).runAsRoot )
            {
                process << "tdesu";
                process << (*it).command;
            }
            else
                process << TQStringList::split( ' ', (*it).command );

            process.start( TDEProcess::DontCare );
            break;
        }
    }
}

#include "interfaceicon.moc"