
#include <qdialog.h>
#include <qgroupbox.h>
#include <qhbox.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qslider.h>
#include "mywidget.h"
#include "decoder_config.h"

#include <creators.h>
#include <videodecoder.h>
#include <cstdio>

using namespace std;
using namespace Creators;
extern DrawEvent g_event;

QConfDialog::QConfDialog(const CodecInfo& _info, IRtConfig* _rt)
    :QDialog(0, "", true), info(_info), attrs(_info.decoder_info), rt(_rt)
{
    setCaption("Video decoder configuration");

    QVBoxLayout *top_vbl = new QVBoxLayout(this, 5);
    top_vbl->setSpacing(2);

    for (unsigned i = 0; i < attrs.size(); i++)
    {
	if (attrs[i].kind == AttributeInfo::Integer)
	{
	    if (attrs[i].i_min + 1 >= attrs[i].i_max)
		continue;//integers with unlimited values 
			 //and boolean attributes are not supported
	    QGroupBox* box = new QGroupBox(this, attrs[i].about.c_str());
	    top_vbl->addWidget(box);

	    box->setColumnLayout(0, Qt::Vertical);
	    //box->setBackgroundColor(QColor(0,100,200));
	    box->setTitle(attrs[i].about.c_str());

	    QVBoxLayout *box_vbl = new QVBoxLayout(box->layout());

	    QSlider* slider = new QSlider(box, "Slider");
            box_vbl->addWidget(slider);
	    slider->setOrientation(QSlider::Horizontal);
	    slider->setTickmarks(QSlider::Both);
	    slider->setMinValue(attrs[i].i_min);
	    slider->setMaxValue(attrs[i].i_max);
	    if (attrs[i].i_max-attrs[i].i_min < 20)
	    {
		slider->setLineStep(1);
	        slider->setPageStep(1);
	    }
	    else
	    {
		slider->setLineStep((attrs[i].i_max-attrs[i].i_min) / 10);
		slider->setPageStep((attrs[i].i_max-attrs[i].i_min) / 10);
	    }

	    items.push_back(static_cast<QObject*>(slider));

	    int val = 0;
	    if (GetCodecAttr(info, attrs[i].name.c_str(), val) == 0)
	    {
		slider->setValue(val);
	    }
            // so we have arrays of the same lenght
	    original.push_back(val);

	    if (rt)
		connect(slider, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));

	    QGroupBox *gbox = new QGroupBox(box);
	    gbox->setFrameStyle(QFrame::NoFrame);
            box_vbl->addWidget(gbox);
	    QHBoxLayout *box_hbl = new QHBoxLayout(gbox);

	    char txt[100];
	    sprintf(txt, "%d", attrs[i].i_min);
	    QLabel* label = new QLabel(gbox, "");
	    label->setText(txt);
            box_hbl->addWidget(label);
	    box_hbl->addStretch(1);
	    sprintf(txt, "%d", attrs[i].i_max);
	    label = new QLabel(gbox, "");
	    label->setText(txt);
            box_hbl->addWidget(label);

	    box_vbl->setStretchFactor(box_hbl, 1);
	}
	//other types of atributes are not supported
    }

    top_vbl->addStretch(1);

    QHBox* hbox = new QHBox(this);
    top_vbl->addWidget(hbox);

    QPushButton* b_ok=new QPushButton("Ok", hbox);
    connect(b_ok, SIGNAL(clicked()), this, SLOT(accept()));

    if(rt)
    {
	QPushButton* b_reset = new QPushButton("Reset", hbox);
	connect(b_reset, SIGNAL(clicked()), this, SLOT(reset()));
    }

    QPushButton* b_cancel=new QPushButton("Cancel", hbox);
    connect(b_cancel, SIGNAL(clicked()), this, SLOT(reject()));
}

void QConfDialog::valueChanged(int)
{
    for(unsigned i = 0; i < attrs.size(); i++)
    {
        QSlider* slider;
        if ((slider = dynamic_cast<QSlider*>(items[i])))
	{
	    int v = slider->value();
	    SetCodecAttr(info, attrs[i].name.c_str(), v);
	    if (rt)
		rt->SetValue(attrs[i].name.c_str(), v);
	}
    }
}

void QConfDialog::reject()
{
    // restore original values & reject
    //cout << "attr size " << attrs.size() << endl;
    for(unsigned i = 0; i < attrs.size(); i++)
    {
        QSlider* slider;
	if ((slider = dynamic_cast<QSlider*>(items[i])))
            if (original[i] != slider->value())
		slider->setValue(original[i]);
    }

    return QDialog::reject();
}

void QConfDialog::reset()
{
    for(unsigned i = 0; i < attrs.size(); i++)
    {
	QSlider* slider;
	if ((slider = dynamic_cast<QSlider*>(items[i])))
	    // invoke valueChanged
	    slider->setValue((attrs[i].i_min + attrs[i].i_max) / 2);
    }
}

void MyWidget::decoder_config()
{
    if (!player || !player->IsValid())
	return;
    IRtConfig* rt = player->GetRuntimeConfig();
    QConfDialog qdlg(player->GetCodecInfo(), rt);
    if (qdlg.exec() == QDialog::Accepted)
    {
	_in_reseek = 1;
	if (!rt)
	    player->Restart();
	//this call blocks until main processing thread
	//is stopped, so it can safely restart decoder.
	//Operations with _in_reseek and mutex guarantee that
	//we won't receive a deadlock.
	_in_reseek = 0;
    }
}

#include "decoder_config.moc"
