#include "tmixtray.h"
#include "tmixpopup.h"
#include "mixerwindow.h"
#include "devicewidget.h"

class RecordingTray : public KSystemTray
{
public:
    RecordingTray( TmixTray *owner, TQWidget *parent )
        : KSystemTray(parent), m_owner(owner) {}
protected:
    void mousePressEvent( TQMouseEvent *e ) {
        if ( e->button() == TQt::LeftButton ) {
            m_owner->toggleRecordingPopup();
            e->accept();
        } else {
            e->accept();
        }
    }
private:
    TmixTray *m_owner;
};
#include "../model/audiodevice.h"
#include "../model/pulsemodel.h"

#include <tqevent.h>
#include <tqpixmap.h>
#include <tqstringlist.h>
#include <tqtooltip.h>
#include <tqapplication.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <tdestandarddirs.h>
#include <tdelocale.h>
#include <tdeconfig.h>
#include <tdepopupmenu.h>

TmixTray::TmixTray( TQWidget *parent )
    : KSystemTray(parent), m_model(0), m_device(0), m_recTray(0),
      m_popup(0), m_recPopup(0), m_popupMode(-1),
      m_popupShowOutput(false), m_popupShowMic(false), m_popupShowApps(false),
      m_recordingCount(0)
{
    setCaption( i18n("Volume Control") );

    TQPixmap titleIcon = TDEGlobal::iconLoader()->loadIcon(
        "tmix", TDEIcon::Small, 16, TDEIcon::DefaultState, 0, true );
    if ( titleIcon.isNull() )
        titleIcon = TDEGlobal::iconLoader()->loadIcon(
            "audio-volume-medium", TDEIcon::Small, 16, TDEIcon::DefaultState, 0, true );
    contextMenu()->changeTitle( contextMenu()->idAt(0), titleIcon, i18n("Volume Control") );

    updateIcon();
}

void TmixTray::setDevice( AudioDevice *dev )
{
    if ( m_device )
        disconnect( m_device, 0, this, 0 );
    m_device = dev;
    if ( m_device ) {
        connect( m_device, TQ_SIGNAL(volumeChanged(int)), this, TQ_SLOT(updateIcon()) );
        connect( m_device, TQ_SIGNAL(muteChanged(bool)),  this, TQ_SLOT(updateIcon()) );
    }
    updateIcon();
}

void TmixTray::setModel( PulseModel *model )
{
    m_model = model;
    connect( model, TQ_SIGNAL(deviceAdded(AudioDevice*)),
             this,  TQ_SLOT(onDeviceAdded(AudioDevice*)) );
    connect( model, TQ_SIGNAL(deviceRemoved(AudioDevice*)),
             this,  TQ_SLOT(onDeviceRemoved(AudioDevice*)) );
    // Count any Recording devices already present (e.g. after reconnect).
    TQPtrList<AudioDevice> recs = model->devices( AudioDevice::Recording );
    for ( TQPtrListIterator<AudioDevice> it(recs); *it; ++it )
        m_recordingCount++;
    updateRecordingTray();
}

void TmixTray::mousePressEvent( TQMouseEvent *e )
{
    if ( e->button() == TQt::LeftButton ) {
        if ( !m_model ) { KSystemTray::mousePressEvent(e); return; }
        executeSingleClick();
        e->accept();
        return;
    }
    if ( e->button() == TQt::MidButton && m_device ) {
        TDEConfig *cfg = TDEGlobal::config();
        cfg->setGroup("Tray");
        if ( cfg->readBoolEntry("MiddleClickMute", false) ) {
            m_device->setMuted( !m_device->muted() );
            e->accept();
            return;
        }
    }
    KSystemTray::mousePressEvent( e );
}


void TmixTray::executeSingleClick()
{
    TDEConfig *cfg = TDEGlobal::config();
    cfg->setGroup("Tray");
    int  mode       = cfg->readNumEntry( "PopupMode",       1     );
    bool showOutput = cfg->readBoolEntry("PopupShowOutput", true  );
    bool showMic    = cfg->readBoolEntry("PopupShowMic",    false );
    bool showApps   = cfg->readBoolEntry("PopupShowApps",   true  );

    if ( mode >= 1 ) {
        if ( m_popup && ( mode       != m_popupMode       ||
                          showOutput != m_popupShowOutput  ||
                          showMic    != m_popupShowMic     ||
                          showApps   != m_popupShowApps    ) ) {
            delete m_popup;
            m_popup = 0;
        }
        if ( !m_popup ) {
            m_popupMode       = mode;
            m_popupShowOutput = showOutput;
            m_popupShowMic    = showMic;
            m_popupShowApps   = showApps;
            m_popup = new TmixPopup( m_model, showOutput, showMic, showApps, false, this );
        }
        if ( m_popup->justHidden() ) return;
        m_popup->toggleAt( mapToGlobal( TQPoint(0,0) ), size() );
    } else {
        MixerWindow *win = static_cast<MixerWindow*>( parentWidget() );
        if ( win->isVisible() )
            win->hide();
        else
            win->bringToFront();
    }
}

void TmixTray::updateIcon()
{
    int  vol  = m_device ? m_device->volume() : 0;
    bool mute = m_device ? m_device->muted()  : true;

    const char *pic;
    if ( mute || vol == 0 )  pic = "audio-volume-muted.png";
    else if ( vol < 34 )     pic = "audio-volume-low.png";
    else if ( vol < 67 )     pic = "audio-volume-medium.png";
    else                     pic = "audio-volume-high.png";

    TQString path = TDEGlobal::dirs()->findResource( "data",
        TQString("tmix/pics/crystal/") + pic );
    if ( !path.isEmpty() )
        setPixmap( TQPixmap(path) );
}

void TmixTray::onRecordingActive( bool /*active*/ )
{
    // Kept for any future per-source signal use; recording count is now
    // driven by onDeviceAdded/onDeviceRemoved for Recording devices.
}

void TmixTray::onDeviceAdded( AudioDevice *dev )
{
    if ( dev->category() == AudioDevice::Recording ) {
        m_recordingCount++;
        updateRecordingTray();
    }
}

void TmixTray::onDeviceRemoved( AudioDevice *dev )
{
    if ( dev->category() == AudioDevice::Recording ) {
        if ( m_recordingCount > 0 )
            m_recordingCount--;
        updateRecordingTray();
    }
}

void TmixTray::updateRecordingTray()
{
    TDEConfig *cfg = TDEGlobal::config();
    cfg->setGroup("Tray");
    bool showRec = cfg->readBoolEntry("ShowRecordingTray", true);

    if ( m_recordingCount > 0 && showRec ) {
        if ( !m_recTray ) {
            m_recTray = new RecordingTray( this, parentWidget() );
            m_recTray->setCaption( i18n("Microphone Active") );

            TQString path = TDEGlobal::dirs()->findResource( "data",
                "tmix/pics/mix_microphone_recording.png" );
            if ( path.isEmpty() )
                path = TDEGlobal::dirs()->findResource( "data",
                    "tmix/pics/mix_microphone.png" );

            if ( !path.isEmpty() )
                m_recTray->setPixmap( TQPixmap( path ) );
        }

        // Build tooltip: list names of active recording streams
        if ( m_model ) {
            TQStringList names;
            TQPtrList<AudioDevice> streams = m_model->devices( AudioDevice::Recording );
            for ( TQPtrListIterator<AudioDevice> it(streams); *it; ++it )
                names.append( (*it)->name() );
            TQString tip = names.isEmpty()
                ? i18n("Microphone in use")
                : i18n("Recording: ") + names.join(", ");
            TQToolTip::add( m_recTray, tip );
        }

        m_recTray->show();
    } else if ( m_recTray ) {
        m_recTray->hide();
        if ( m_recPopup && m_recPopup->isVisible() )
            m_recPopup->hide();
    }
}

void TmixTray::toggleRecordingPopup()
{
    if ( !m_model ) return;
    if ( !m_recPopup )
        m_recPopup = new TmixPopup( m_model,
                                    false /*output*/, true /*mic*/,
                                    false /*apps*/, true /*recording*/,
                                    0 );
    if ( m_recPopup->justHidden() ) return;
    TQPoint pos = m_recTray->mapToGlobal( TQPoint(0,0) );
    m_recPopup->toggleAt( pos, m_recTray->size() );
}

void TmixTray::wheelEvent( TQWheelEvent *e )
{
    if ( !m_device ) return;
    TDEConfig *cfg = TDEGlobal::config();
    cfg->setGroup("Tray");
    int step = cfg->readNumEntry("ScrollStep", 5);
    int delta  = e->delta() > 0 ? step : -step;
    int newVol = m_device->volume() + delta;
    if ( newVol < 0 )   newVol = 0;
    if ( newVol > 100 ) newVol = 100;
    m_device->setVolume( newVol );
}

void TmixTray::contextMenuAboutToShow( TDEPopupMenu *menu )
{
    while ( menu->count() > 1 )
        menu->removeItemAt( 1 );

    MixerWindow *win = static_cast<MixerWindow*>( parentWidget() );

    menu->insertItem( SmallIcon("tmix"), i18n("&Open Mixer"),
                      win, TQ_SLOT(bringToFront()) );
    menu->insertItem( i18n("&Open Devices"),
                      win, TQ_SLOT(showDevices()) );
    menu->insertSeparator();
    menu->insertItem( SmallIcon("configure"), i18n("&Configure TMix..."),
                      win, TQ_SLOT(showPreferences()) );
    menu->insertItem( SmallIcon("help"), i18n("&About TMix"),
                      win, TQ_SLOT(showAbout()) );
    menu->insertSeparator();
    menu->insertItem( SmallIcon("application-exit"), i18n("&Quit"),
                      win, TQ_SLOT(quit()) );
}

#include "tmixtray.moc"
