#include <cpuinfo.h>
#include <videoencoder.h>
#include <creators.h>

#include <configfile.h>

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
#include "codecconf.h"
#include <qlistbox.h>
#include <qcombobox.h>
#include <qdial.h>
#include <qlayout.h>
#include <qlistview.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qmessagebox.h>
#include <qtextview.h>
#include <qlabel.h>
#include <qtextbrowser.h>

using namespace Registry;
using namespace Creators;
class QMyMessageBox: public QDialog
{
    QLabel* label;
    QPushButton* ok;
//    QTextBrowser* browser;
//    QTextView* view;
    public:
	QMyMessageBox(QWidget* parent, QString title, QString content)
	    :QDialog(parent, title, true, 0)
	{
	    QGridLayout* qgl = new QGridLayout(this);
            qgl->setMargin(10);
            qgl->setSpacing(10);
	    label=new QLabel(this);
	    label->setTextFormat(QLabel::RichText);
	    label->setText(QString("<p align=center>")+content);
	    label->setAlignment(Qt::WordBreak | Qt::AlignVCenter | Qt::AlignHCenter);
	    label->setFrameShadow(QLabel::Sunken);
            qgl->addMultiCellWidget(label, 0, 0, 0, 2);
	    ok=new QPushButton("Ok", this);
            qgl->setColStretch(0, 1);
            qgl->addWidget(ok, 1, 1); // centered
            qgl->setColStretch(2, 1);
	    connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
/*	    
	    browser=new QTextBrowser(this);
	    browser->resize(100,150);
	    browser->move(140, 20);
	    browser->setText(content);
//	    browser->setAlignment(Qt::WordBreak | Qt::AlignVCenter | Qt::AlignHCenter);

	    view=new QTextView(this);
	    view->resize(100,150);
	    view->move(260, 20);
	    view->setText(content);
//	    view->setAlignment(Qt::WordBreak | Qt::AlignVCenter | Qt::AlignHCenter);
*/
	}  
    static void QMyMessageBox::about(QWidget* parent, QString title, QString content)
    {
	QMyMessageBox box(parent, title, content);
	box.exec();
    }
};	  

class QInputInteger: public QDialog
{
    QLineEdit* _edit;
    QPushButton* _ok;
    QPushButton* _cancel;
    int _defval;
    public:
	QInputInteger(QWidget* parent, QString title, int defval)
	    :QDialog(parent, title, true, 0), _defval(defval)
	    {
		resize(275,80);
		char txt[256];
		sprintf(txt, "%d", defval);
		QGridLayout* qgl = new QGridLayout(this);
		qgl->setMargin(10);
		qgl->setSpacing(10);
		_edit=new QLineEdit(txt, this);
                qgl->addMultiCellWidget(_edit, 0, 0, 0, 3);

		qgl->setColStretch(0, 1);
		_ok=new QPushButton("Ok", this);
                qgl->addWidget(_ok, 1,1);
		connect(_ok, SIGNAL(clicked()), this, SLOT(accept()));
		
		_cancel=new QPushButton("Cancel", this);
                qgl->addWidget(_cancel, 1,2);
		connect(_cancel, SIGNAL(clicked()), this, SLOT(reject()));
		
		setCaption(QString("Enter new ")+title);
	    }
	virtual void accept()
	{
	    _defval=atoi(_edit->text());
	    return QDialog::accept();
	}
	int value(){return _defval;}
};	    


class QInputString: public QDialog
{
    QLineEdit* _edit;
    QPushButton* _ok;
    QPushButton* _cancel;
    std::string _defval;
    public:
	QInputString(QWidget* parent, QString title, const char* defval)
	    :QDialog(parent, title, true, 0), _defval(defval)
	    {
		resize(275,80);
		QGridLayout* qgl = new QGridLayout(this);
		qgl->setMargin(10);
		qgl->setSpacing(10);
		_edit=new QLineEdit(defval, this);
                qgl->addMultiCellWidget(_edit, 0, 0, 0, 3);
		
		qgl->setColStretch(0, 1);
		_ok=new QPushButton("Ok", this);
		connect(_ok, SIGNAL(clicked()), this, SLOT(accept()));
                qgl->addWidget(_ok, 1,1);
		
		_cancel=new QPushButton("Cancel", this);
                qgl->addWidget(_cancel, 1,2);
		connect(_cancel, SIGNAL(clicked()), this, SLOT(reject()));
		
		setCaption(QString("Enter new ")+title);
	    }
	virtual void accept()
	{
	    _defval=_edit->text().ascii();
	    return QDialog::accept();
	}
	const char* value(){return _defval.c_str();}
};	    


class QInputSelect: public QDialog
{
    QComboBox* _box;
    QPushButton* _ok;
    QPushButton* _cancel;
    const std::vector<std::string>& _options;
    int _defval;
    public:
	QInputSelect(QWidget* parent, QString title, const std::vector<std::string>& options, int defval)
	    :QDialog(parent, title, true, 0), _options(options), _defval(defval)
	    {
		resize(275,80);
		char txt[256];
		sprintf(txt, "%d", defval);
		_box=new QComboBox(txt, this);
		_box->move(20,10);
		_box->resize(235,25);
		
		std::vector<std::string>::const_iterator it;
		int i=0;
		for(it=_options.begin(); it!=_options.end(); it++)
		    _box->insertItem(_options[i].c_str(), i++); 
		_box->setCurrentItem(_defval);
		
		_ok=new QPushButton("Ok", this);
		_ok->move(170, 45);
		_ok->resize(45,25);
		connect(_ok, SIGNAL(clicked()), this, SLOT(accept()));
		
		_cancel=new QPushButton("Cancel", this);
		_cancel->move(220, 45);
		_cancel->resize(45,25);
		connect(_cancel, SIGNAL(clicked()), this, SLOT(reject()));
		
		setCaption(QString("Enter new ")+title);
	    }
	virtual void accept()
	{
	    _defval=_box->currentItem();
	    return QDialog::accept();
	}
	int value(){return _defval;}
};	    


CodecConfig::CodecConfig( QWidget* parent, VideoEncoderInfo info )
    : CodecConfigDialog( parent, "Select video codec", true, 0 )
{
    _listCodecs->clear();
    std::vector<CodecInfo>::iterator it;
    int i=0;
    int sel=0;
    for(it=video_codecs.begin(); it!=video_codecs.end(); it++)
    {
	if(!(it->direction&CodecInfo::Encode))continue;
	_listCodecs->insertItem(it->text.c_str());
	if(it->fourcc==info.compressor)
	    sel=i;
	i++;
    }
    
    connect(_listCodecs, SIGNAL(selectionChanged()), this, SLOT(SelectCodec()));
    
    _pQuality->setValue(info.quality/100);
    _pKeyframe->setValue(info.keyfreq);
        
    _listCodecs->setCurrentItem(sel);
    SelectCodec();
}

void CodecConfig::accept()
{
    return QDialog::accept();
}
/*  
 *  Destroys the object and frees any allocated resources
 */
CodecConfig::~CodecConfig()
{
    // no need to delete child widgets, Qt does it all for us
}

VideoEncoderInfo CodecConfig::GetInfo()
{
    VideoEncoderInfo info;
    int i=0, j=0;
    int codec=_listCodecs->currentItem();
    std::vector<CodecInfo>::iterator iv;
    for(iv=video_codecs.begin(); iv!=video_codecs.end(); iv++, i++)
    {
	if(!(iv->direction&CodecInfo::Encode))continue;
	if(j==codec)break;
	j++;
    }
    codec=i;
    info.compressor=video_codecs[codec].fourcc;
    info.cname = video_codecs[codec].text;
    info.quality = _pQuality->value()*100;
    info.keyfreq = _pKeyframe->value();
    return info;
}

void CodecConfig::SelectCodec()
{
    int codec=_listCodecs->currentItem();
    int i=0, j=0;
    std::vector<CodecInfo>::const_iterator iv;
    for (iv = video_codecs.begin(); iv != video_codecs.end(); iv++, i++)
    {
	if (!(iv->direction&CodecInfo::Encode))
	    continue;
	if (j == codec)
	    break;
	j++;
    }
    codec = i;
    const std::vector<AttributeInfo> ci=video_codecs[codec].encoder_info;
    _tabAttr->clear();
    _tabAttr->setSorting(0, false);
    _tabAttr->setSorting(1, false);

    std::vector<AttributeInfo>::const_iterator it;
    for (it = ci.begin(); it != ci.end(); it++)
    {
	// std::cerr << "attr" <<it->name<<std::endl;
	QListViewItem* item = new QListViewItem(_tabAttr);
	item->setText(0, it->name.c_str());
	char tmp[256];
	std::string val = "<none>";
	std::string s;
	int param; 
	switch(it->kind)
	{
	case AttributeInfo::Integer:
	    if (GetCodecAttr(video_codecs[codec], it->name.c_str(), param) == 0)
	    {
	    	//val=itoa(param, tmp, 10);
	    	sprintf(tmp, "%d", param);
		val = tmp;
	    }
	    break;
	case AttributeInfo::Select:
	    if (GetCodecAttr(video_codecs[codec], it->name.c_str(), param) == 0)
	    {
		//val=itoa(param, tmp, 10);
	    	sprintf(tmp, "%d", param);
		val = tmp;
		val += " ( ";
		val += it->options[param];
		val += " )";
		break;
	    }
	case AttributeInfo::String:
	    GetCodecAttr(video_codecs[codec], it->name.c_str(), tmp, sizeof(tmp));
	    val = tmp;
	    break;
	}
	item->setText(1, val.c_str());
    }
}

void CodecConfig::change_attr(QListViewItem* item)
{
    QString str=item->text(0);
    int defval=0;
    char def_str[256];
    int codec=_listCodecs->currentItem();
    int i=0, j=0;
    std::vector<CodecInfo>::iterator iv;
    for(iv=video_codecs.begin(); iv!=video_codecs.end(); iv++, i++)
    {
	if(!(iv->direction&CodecInfo::Encode))continue;
	if(j==codec)break;
	j++;
    }
    codec=i;
    std::cerr<<"Getting "<<str.ascii()<<" for "<<video_codecs[codec].text<<std::endl;
    QInputInteger* inp;
    QInputSelect* qit;
    QInputString* qis;
    const std::vector<AttributeInfo> ci=video_codecs[codec].encoder_info;
    std::vector<AttributeInfo>::const_iterator it;
    for(it=ci.begin(); it!=ci.end(); it++)
	if(!strcmp(it->name.c_str(), str.ascii()))
	    break;
    switch(it->kind)
    {
	case AttributeInfo::Integer:    
	GetCodecAttr(video_codecs[codec], str.ascii(), defval);
	    inp=new QInputInteger(this, str+QString(" value"), defval);
	    if(inp->exec()==QDialog::Accepted)
	    {
		std::cerr<<"Setting "<<str.ascii()<<" to "<<inp->value()<<" for "<<video_codecs[codec].text<<std::endl;
		SetCodecAttr(video_codecs[codec], str.ascii(), inp->value());
		SelectCodec();
	    }
	    delete inp;
	    break;
	case AttributeInfo::Select:
	    GetCodecAttr(video_codecs[codec], str.ascii(), defval);
	    qit=new QInputSelect(this, str+QString(" value"), it->options, defval);
	    if(qit->exec()==QDialog::Accepted)
            {
		std::cerr<<"Setting "<<str.ascii()<<" to "<<qit->value()<<" for "<<video_codecs[codec].text<<std::endl;
	        SetCodecAttr(video_codecs[codec], str.ascii(), qit->value());
		SelectCodec();
	    }	
	    delete qit;
	    break;
	case AttributeInfo::String:
	    GetCodecAttr(video_codecs[codec], str.ascii(), def_str, 256);
	    qis=new QInputString(this, str+QString(" value"), def_str);
	    if(qis->exec()==QDialog::Accepted)
            {
		std::cerr<<"Setting "<<str.ascii()<<" to "<<qis->value()<<" for "<<video_codecs[codec].text<<std::endl;
	        SetCodecAttr(video_codecs[codec], str.ascii(), qis->value());
		SelectCodec();
	    }	
	    delete qis;
	    break;
    }	    
}

void CodecConfig::about_clicked()
{
    int codec = _listCodecs->currentItem();
    int i=0, j=0;

    vector<CodecInfo>::iterator iv;
    for (iv = video_codecs.begin(); iv != video_codecs.end(); iv++, i++)
    {
	if (!(iv->direction & CodecInfo::Encode))
	    continue;
	if (j == codec)
	    break;
	j++;
    }
    codec=i;
    QMyMessageBox::about(this, video_codecs[codec].text.c_str(),
			 video_codecs[codec].about.c_str());
}

#include "codecconf.moc"
#include "codecconf_p.moc"
