#include "ossdevicewidget.h"
#include "../../model/ossdevice.h"
#include "../balanceknob.h"
#include "../kledbutton.h"

#include <tqlayout.h>
#include <tqslider.h>
#include <tqlabel.h>
#include <tqpixmap.h>
#include <tqpainter.h>
#include <tdeglobal.h>
#include <tdestandarddirs.h>

class VerticalLabel : public TQWidget
{
public:
    VerticalLabel( const TQString &text, TQWidget *parent )
        : TQWidget(parent), m_text(text) { setMinimumSize(20, 10); }
    TQSize sizeHint() const { return TQSize(20, 100); }
    TQSizePolicy sizePolicy() const {
        return TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Expanding);
    }
protected:
    void paintEvent( TQPaintEvent * ) {
        TQPainter p(this);
        TQFontMetrics fm = p.fontMetrics();
        int available = height() - 6;
        TQString text = m_text;
        if ( fm.width(text) > available ) {
            while ( text.length() > 1 && fm.width(text) + fm.width("...") > available )
                text.truncate(text.length() - 1);
            text += "...";
        }
        p.rotate(270);
        p.translate(0, -4);
        p.drawText(-height() + 2, width(), text);
    }
private:
    TQString m_text;
};

static TQPixmap ossPic( const char *name )
{
    TQString path = TDEGlobal::dirs()->findResource("data",
        TQString("tmix/pics/") + name);
    return path.isEmpty() ? TQPixmap() : TQPixmap(path);
}

static TQPixmap iconForDevice( OssDevice *dev )
{
    TQString n = dev->name().lower();
    if ( n == "vol" || n.contains("master") )
        return ossPic("crystal/audio-volume-medium.png");
    if ( n.contains("headphone") || n.contains("headset") )
        return ossPic("mix_headphone.png");
    if ( n.contains("mic") )
        return ossPic("mix_microphone.png");
    if ( n.contains("line") )
        return ossPic("mix_ext.png");
    if ( n.contains("cd") )
        return ossPic("mix_cd.png");
    if ( n.contains("dig") || n.contains("spdif") || n.contains("iec") )
        return ossPic("mix_digital.png");
    if ( n.contains("pcm") || n.contains("wave") )
        return ossPic("mix_audio.png");
    if ( dev->category() == OssDevice::Input )
        return ossPic("mix_microphone.png");
    return ossPic("crystal/audio-volume-medium.png");
}

OssDeviceWidget::OssDeviceWidget( OssDevice *dev, TQWidget *parent )
    : TQWidget(parent), m_dev(dev), m_balance(0)
{
    TQHBoxLayout *outer = new TQHBoxLayout(this, 4, 0);
    outer->addStretch(1);

    TQVBoxLayout *col = new TQVBoxLayout(0, 0, 2);

    TQHBoxLayout *topRow = new TQHBoxLayout(0, 0, 2);
    TQLabel *icon = new TQLabel(this);
    TQPixmap px = iconForDevice(dev);
    if ( !px.isNull() ) icon->setPixmap(px);
    topRow->addWidget(icon, 0, TQt::AlignVCenter);
    m_volLabel = new TQLabel("100%", this);
    m_volLabel->setFixedWidth( m_volLabel->sizeHint().width() + 2 );
    m_volLabel->setAlignment( TQt::AlignRight | TQt::AlignVCenter );
    m_volLabel->setText( TQString("%1%").arg(dev->volume()) );
    topRow->addWidget(m_volLabel, 0, TQt::AlignVCenter);
    col->addLayout(topRow);

    TQHBoxLayout *sliderRow = new TQHBoxLayout(0, 0, 2);
    VerticalLabel *vlabel = new VerticalLabel(dev->name(), this);
    sliderRow->addWidget(vlabel);
    m_slider = new TQSlider(0, 100, 5, 100 - dev->volume(), TQt::Vertical, this);
    m_slider->setTickmarks(TQSlider::Right);
    m_slider->setTickInterval(5);
    m_slider->setMinimumHeight(80);
    sliderRow->addWidget(m_slider, 1);
    col->addLayout(sliderRow, 1);

    TQWidget *bottom = new TQWidget(this);
    bottom->setFixedHeight(30);
    TQHBoxLayout *bottomRow = new TQHBoxLayout(bottom, 0, 2);
    bottomRow->addStretch(1);
    if ( dev->stereo() ) {
        m_balance = new BalanceKnob(-50, 50, dev->pan(), bottom);
        bottomRow->addWidget(m_balance, 0, TQt::AlignVCenter);
        bottomRow->addStretch(1);
        connect(m_balance, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(onPanMoved(int)));
    }
    m_muteBtn = new KLedButton(TQt::green,
        dev->muted() ? KLed::Off : KLed::On,
        KLed::Raised, KLed::Circular, bottom);
    m_muteBtn->setFixedSize(16, 16);
    bottomRow->addWidget(m_muteBtn, 0, TQt::AlignVCenter);
    bottomRow->addStretch(1);
    col->addWidget(bottom, 0);

    outer->addLayout(col);
    outer->addStretch(1);

    connect(dev, TQ_SIGNAL(volumeChanged(int)), this, TQ_SLOT(onVolumeChanged(int)));
    connect(dev, TQ_SIGNAL(muteChanged(bool)),  this, TQ_SLOT(onMuteChanged(bool)));
    connect(dev, TQ_SIGNAL(panChanged(int)),    this, TQ_SLOT(onPanChanged(int)));
    connect(m_slider,  TQ_SIGNAL(valueChanged(int)),  this, TQ_SLOT(onSliderMoved(int)));
    connect(m_muteBtn, TQ_SIGNAL(stateChanged(bool)), this, TQ_SLOT(onMuteToggled(bool)));
}

void OssDeviceWidget::onVolumeChanged( int v )
{
    m_slider->blockSignals(true);
    m_slider->setValue(100 - v);
    m_slider->blockSignals(false);
    m_volLabel->setText(TQString("%1%").arg(v));
}

void OssDeviceWidget::onMuteChanged( bool m )
{
    m_muteBtn->blockSignals(true);
    m_muteBtn->setState(m ? KLed::Off : KLed::On);
    m_muteBtn->blockSignals(false);
}

void OssDeviceWidget::onPanChanged( int p )
{
    if ( m_balance ) {
        m_balance->blockSignals(true);
        m_balance->setValue(p);
        m_balance->blockSignals(false);
    }
}

void OssDeviceWidget::onSliderMoved( int v )  { m_dev->setVolume(100 - v); }
void OssDeviceWidget::onMuteToggled( bool on ) { m_dev->setMuted(!on); }
void OssDeviceWidget::onPanMoved( int p )      { m_dev->setPan(p); }

#include "ossdevicewidget.moc"
