#include "tmixpopup.h"
#include "devicewidget.h"
#include "../model/audiodevice.h"
#include "../model/pulsemodel.h"

#include <tqlayout.h>
#include <tqframe.h>
#include <tqapplication.h>
#include <tqdesktopwidget.h>
#include <tdelocale.h>
#include <tdeconfig.h>
#include <tdeglobal.h>
#include <twin.h>

TmixPopup::TmixPopup( PulseModel *model,
                      bool showOutput, bool showMic, bool showApps,
                      bool showRecording,
                      TQWidget *parent )
    : TQWidget( parent, "TmixPopup",
                WStyle_Customize | WType_Popup | WStyle_DialogBorder ),
      m_model(model), m_showOutput(showOutput),
      m_showMic(showMic), m_showApps(showApps), m_showRecording(showRecording),
      m_devContainer(0)
{
    m_devWidgets.setAutoDelete( true );

    TQVBoxLayout *outer = new TQVBoxLayout( this, 0, 0 );

    TQFrame *frame = new TQFrame( this );
    frame->setFrameStyle( TQFrame::NoFrame );
    outer->addWidget( frame );

    m_outerLayout = new TQVBoxLayout( frame, 0, 0 );

    m_devContainer = new TQWidget( frame );
    m_outerLayout->addWidget( m_devContainer );

    m_outerLayout->addSpacing( 4 );

    connect( model, TQ_SIGNAL(defaultOutputChanged(AudioDevice*)),
             this,  TQ_SLOT(onDefaultOutputChanged(AudioDevice*)) );
    connect( model, TQ_SIGNAL(deviceAdded(AudioDevice*)),
             this,  TQ_SLOT(onDeviceAdded(AudioDevice*)) );
    connect( model, TQ_SIGNAL(deviceRemoved(AudioDevice*)),
             this,  TQ_SLOT(onDeviceRemoved(AudioDevice*)) );

    rebuild();
}

void TmixPopup::rebuild()
{
    m_devWidgets.clear();
    delete m_devContainer->layout();

    TQHBoxLayout *hbox = new TQHBoxLayout( m_devContainer, 4, 0 );
    bool anyAdded = false;

    auto addSep = [&]() {
        if ( !anyAdded ) return;
        TQFrame *sep = new TQFrame( m_devContainer );
        sep->setFrameStyle( TQFrame::VLine | TQFrame::Sunken );
        sep->setFixedWidth( 4 );
        hbox->addWidget( sep );
    };

    auto addWidget = [&]( AudioDevice *dev ) {
        DeviceWidget *w = new DeviceWidget( dev, m_model, m_devContainer );
        w->setSeparatorVisible( false );
        hbox->addWidget( w );
        w->show();
        m_devWidgets.append( w );
        anyAdded = true;
    };

    if ( m_showOutput ) {
        AudioDevice *def = m_model->defaultOutput();
        if ( def ) {
            addSep();
            addWidget( def );
        }
    }

    if ( m_showMic ) {
        TQPtrList<AudioDevice> inputs = m_model->devices( AudioDevice::Input );
        if ( !inputs.isEmpty() ) {
            addSep();
            for ( TQPtrListIterator<AudioDevice> it(inputs); *it; ++it )
                addWidget( *it );
        }
    }

    if ( m_showApps ) {
        TQPtrList<AudioDevice> apps = m_model->devices( AudioDevice::Playback );
        if ( !apps.isEmpty() ) {
            addSep();
            for ( TQPtrListIterator<AudioDevice> it(apps); *it; ++it )
                addWidget( *it );
        }
    }

    if ( m_showRecording ) {
        TQPtrList<AudioDevice> recs = m_model->devices( AudioDevice::Recording );
        if ( !recs.isEmpty() ) {
            addSep();
            for ( TQPtrListIterator<AudioDevice> it(recs); *it; ++it )
                addWidget( *it );
        }
    }

    m_devContainer->show();
    adjustSize();
}

void TmixPopup::onDefaultOutputChanged( AudioDevice * )
{
    if ( m_showOutput )
        rebuild();
}

void TmixPopup::onDeviceAdded( AudioDevice *dev )
{
    AudioDevice::Category cat = dev->category();
    if ( ( m_showMic       && cat == AudioDevice::Input     ) ||
         ( m_showApps      && cat == AudioDevice::Playback  ) ||
         ( m_showRecording && cat == AudioDevice::Recording ) )
        rebuild();
}

void TmixPopup::onDeviceRemoved( AudioDevice *dev )
{
    AudioDevice::Category cat = dev->category();
    if ( ( m_showMic       && cat == AudioDevice::Input     ) ||
         ( m_showApps      && cat == AudioDevice::Playback  ) ||
         ( m_showRecording && cat == AudioDevice::Recording ) )
        rebuild();
}

void TmixPopup::toggleAt( const TQPoint &trayPos, const TQSize &traySize )
{
    if ( isVisible() ) {
        hide();
        return;
    }

    rebuild();
    adjustSize();

    TQRect screen = TQApplication::desktop()->screenGeometry( trayPos );

    int x = trayPos.x() + traySize.width() / 2 - width() / 2;
    int y = trayPos.y() - height();

    if ( y < screen.top() )
        y = trayPos.y() + traySize.height();
    if ( x + width() > screen.right() )
        x = screen.right() - width();
    if ( x < screen.left() )
        x = screen.left();

    move( x, y );
    show();

    KWin::setState( winId(), NET::KeepAbove | NET::SkipTaskbar | NET::SkipPager );
    KWin::setOnAllDesktops( winId(), true );
}

bool TmixPopup::justHidden() const
{
    return m_hideTime.isValid() && m_hideTime.elapsed() < 100;
}

void TmixPopup::showEvent( TQShowEvent *e )
{
    TQWidget::showEvent( e );
    m_model->addLevelViewer();
}

void TmixPopup::hideEvent( TQHideEvent *e )
{
    TQWidget::hideEvent( e );
    m_hideTime.start();
    m_model->removeLevelViewer();
}

void TmixPopup::wheelEvent( TQWheelEvent *e )
{
    // Only intercept scroll in single-output mode — with multiple devices
    // visible, scroll should go to the device widget under the cursor.
    if ( m_showMic || m_showApps || m_showRecording ) { e->ignore(); return; }

    AudioDevice *dev = m_model->defaultOutput();
    if ( !dev ) return;
    TDEConfig *cfg = TDEGlobal::config();
    cfg->setGroup("Tray");
    int step = cfg->readNumEntry("ScrollStep", 5);
    int delta = e->delta() > 0 ? step : -step;
    int vol = TQMAX( 0, TQMIN( 100, dev->volume() + delta ) );
    dev->setVolume( vol );
}

#include "tmixpopup.moc"
