/* This file is NOT part of KDE ;)
   Copyright (C) 2007 Andreas Hartmetz <ahartmetz@gmail.com>

   This application 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.

   This library 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 "mixerwidget.h"
#include "volumewidget.h"

#include <kglobal.h>
#include <kdebug.h>
#include <kicon.h>
#include <klocale.h>

#include <phonon/objectdescription.h>
#include "../mixer/mixerlist.h"
#include "../mixer/mixer.h"
#include "../mixer/mixerelement.h"
#include "../mixer/mixercontrol.h"
#include "../mixer/mixercontrolset.h"
#include "../mixer/mixerintegercontrol.h"
#include "../mixer/mixerenumcontrol.h"
#include "../mixer/mixertogglecontrol.h"

#include <QtGui/QCheckBox>
#include <QtGui/QToolButton>
#include <QtGui/QComboBox>
#include <QtGui/QLabel>
#include <QtGui/QSlider>
#include <QtGui/QVBoxLayout>

K_GLOBAL_STATIC_WITH_ARGS(KIcon, s_volumeIcon, ("player-volume"))
K_GLOBAL_STATIC_WITH_ARGS(KIcon, s_volumeMutedIcon, ("player-volume-muted"))

namespace Phonon
{
namespace Mixer
{

MixerWidget::MixerWidget(const MixerControl &ctrl, QWidget *parent)
    : QWidget(parent),
    m_control(new MixerControl(ctrl)),
    m_controlSet(0)
{
    if (!m_control->isValid()) {
        return;
    }

    QVBoxLayout *layout = new QVBoxLayout(this);
    switch(ctrl.type()) {
    case MixerControl::Toggle: { //scoping
        QCheckBox *cb = new QCheckBox(this);
        layout->addWidget(cb);
        MixerToggleControl tc = mixercontrol_cast<MixerToggleControl>(ctrl);

        cb->setCheckState(tc.isChecked() ? Qt::Checked : Qt::Unchecked);
        connect(cb, SIGNAL(toggled(bool)), ctrl, SLOT(setChecked(bool)));
        connect(ctrl, SIGNAL(toggled(bool)), cb, SLOT(setChecked(bool)));
        connect(ctrl, SIGNAL(toggled(bool)), this, SLOT(showNewValue(bool)));
        break; }

    case MixerControl::Integer: { //scoping
        QSlider *slider = new QSlider(this);
        layout->addWidget(slider);
        MixerIntegerControl ic = mixercontrol_cast<MixerIntegerControl>(ctrl);

        slider->setMinimum(ic.minimumValue());
        slider->setMaximum(ic.maximumValue());
        slider->setValue(ic.value());
        connect(slider, SIGNAL(valueChanged(int)), ctrl, SLOT(setValue(int)));
        connect(ctrl, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
        connect(ctrl, SIGNAL(valueChanged(int)), this, SLOT(showNewValue(int)));
        break; }

    case MixerControl::Enum: { //scoping
        QComboBox *cb = new QComboBox(this);
        layout->addWidget(cb);
        //should we rather use an array of radio buttons?
        MixerEnumControl ec = mixercontrol_cast<MixerEnumControl>(ctrl);

        cb->insertItems(0, ec.options());
        connect(cb, SIGNAL(currentIndexChanged(int)), ctrl, SLOT(setCurrentIndex(int)));
        connect(ctrl, SIGNAL(currentIndexChanged(int)), cb, SLOT(setCurrentIndex(int)));
        break; }

    default:
        layout->addWidget(new QLabel("invalid control", this));
    }
}

MixerWidget::MixerWidget(const MixerControlSet &ctrlSet, QWidget *parent)
    : QWidget(parent),
    m_control(0),
    m_controlSet(new MixerControlSet(ctrlSet))
{
    if (!m_controlSet->isValid()) {
        return;
    }

    QVBoxLayout *topLayout = new QVBoxLayout(this);

    QList<MixerToggleControl> toggleControls = m_controlSet->toggleControls();
    if (!toggleControls.isEmpty()) {
        QHBoxLayout *layout = new QHBoxLayout();
        topLayout->addLayout(layout);
        topLayout->setAlignment(layout, Qt::AlignHCenter | Qt::AlignTop);
        foreach (const MixerToggleControl &tc, toggleControls) {
            switch (tc.category()) {
            case MixerToggleControl::MuteLeftSwitch:
            case MixerToggleControl::MuteRightSwitch:
            case MixerToggleControl::MuteMonoSwitch:
                {
                    QToolButton *button = new QToolButton(this);
                    layout->addWidget(button);

                    button->setIconSize(QSize(22, 22));
                    button->setAutoRaise(true);
                    button->setCheckable(true);
                    if (tc.isChecked()) {
                        button->setIcon(*s_volumeIcon);
                        button->setChecked(true);
                        button->setToolTip(i18n("unmuted"));
                    } else {
                        button->setIcon(*s_volumeMutedIcon);
                        button->setChecked(false);
                        button->setToolTip(i18n("muted"));
                    }
                    connect(button, SIGNAL(toggled(bool)), tc, SLOT(setChecked(bool)));
                    connect(button, SIGNAL(toggled(bool)), this, SLOT(updateButton(bool)));
                    connect(tc, SIGNAL(toggled(bool)), button, SLOT(setChecked(bool)));
                    connect(tc, SIGNAL(toggled(bool)), this, SLOT(showNewValue(bool)));
                }
                break;
            }
        }
    }

    QList<MixerIntegerControl> integerControls = m_controlSet->integerControls();
    if (!integerControls.isEmpty()) {
        QHBoxLayout *layout = new QHBoxLayout();
        topLayout->addLayout(layout);
        foreach (const MixerIntegerControl &ic, integerControls) {
            QSlider *slider = new QSlider(this);
            layout->addWidget(slider);

            slider->setMinimum(ic.minimumValue());
            slider->setMaximum(ic.maximumValue());
            slider->setValue(ic.value());
            connect(slider, SIGNAL(valueChanged(int)), ic, SLOT(setValue(int)));
            connect(ic, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
            connect(ic, SIGNAL(valueChanged(int)), this, SLOT(showNewValue(int)));
        }
    }

    QList<MixerEnumControl> enumControls = m_controlSet->enumControls();
    if (!enumControls.isEmpty()) {
        foreach (const MixerEnumControl &ec, enumControls) {
            QComboBox *cb = new QComboBox(this);
            topLayout->addWidget(cb);
            topLayout->setAlignment(cb, Qt::AlignHCenter | Qt::AlignTop);
            //should we rather use an array of radio buttons?

            cb->insertItems(0, ec.options());
            connect(cb, SIGNAL(currentIndexChanged(int)), ec, SLOT(setCurrentIndex(int)));
            connect(ec, SIGNAL(currentIndexChanged(int)), cb, SLOT(setCurrentIndex(int)));
        }
    }
}

static VolumeWidget *s_volumeWidget = 0;

void MixerWidget::showNewValue(int value)
{
    if (!s_volumeWidget) {
        s_volumeWidget = new VolumeWidget(this);
    }

    if (m_control) {
        MixerIntegerControl ic = mixercontrol_cast<MixerIntegerControl>(*m_control);
        Q_ASSERT(ic.isValid());
        s_volumeWidget->setPercentage(value * 100 / ic.maximumValue());
    } else {
        Q_ASSERT(m_controlSet);
        MixerIntegerControl ic = qobject_cast<MixerIntegerControl>(sender());
        Q_ASSERT(ic.isValid());
        s_volumeWidget->setPercentage(value * 100 / ic.maximumValue());
    }
}

void MixerWidget::showNewValue(bool value)
{
    if (!s_volumeWidget) {
        s_volumeWidget = new VolumeWidget(this);
    }
    s_volumeWidget->setMuted(!value);
}

void MixerWidget::updateButton(bool state)
{
    QToolButton *button = qobject_cast<QToolButton *>(sender());
    Q_ASSERT(button);
    if (state) {
        button->setIcon(*s_volumeIcon);
        button->setToolTip(i18n("unmuted"));
    } else {
        button->setIcon(*s_volumeMutedIcon);
        button->setToolTip(i18n("muted"));
    }
}

MixerWidget::~MixerWidget()
{
    delete s_volumeWidget;
    s_volumeWidget = 0;
}

} // namespace Mixer
} // namespace Phonon
