#include "vequalizer.h"
#define EQVIEW_CPP
#include "equalizerview.h"
#undef EQVIEW_CPP
#include "equalizerwidget.h"
#include "app.h"

#include <knuminput.h>
#include <kdialog.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <tdelocale.h>

#include <tqlayout.h>
#include <tqslider.h>
#include <tqcheckbox.h>
#include <tqlabel.h>
#include <tqtabwidget.h>
#include <tqpushbutton.h>
#include <tqheader.h>
#include <tqfileinfo.h>
#include <tqhbox.h>
#include <tqvbox.h>
#include <tqframe.h>
#include <tqgroupbox.h>

#define EQ (napp->vequalizer())


////////////////////////////////////////////////
// PresetList

PresetList::PresetList(TQWidget *parent, const char *name)
	: TDEListView(parent, name)
{
	setItemsRenameable(true);
	setRenameable(0, true);
	addColumn(""); // first column is the visible one
	addColumn("", 0); // create one column to store cruft in
	setColumnWidthMode(0, TQListView::Maximum);
	header()->setStretchEnabled(true,0);
	header()->hide();
	// a try to set a sne minimum width. unfortuately the custom item
	// still doesn't draw all text with that minimum width
	setMinimumWidth(kapp->fontMetrics().boundingRect(i18n("Custom")).width()+2*itemMargin());
}

void PresetList::rename(TQListViewItem *item, int c)
{
	// We can't rename the "Custom" metapreset
	if (item->text(0)==i18n("Custom"))
		return;

	// Or presets we don't have write access to
	if (!TQFileInfo(item->text(1)).isWritable())
		return;

	TDEListView::rename(item, c);
}

////////////////////////////////////////////////
// EqualizerLevel

EqualizerLevel::EqualizerLevel(TQWidget *parent, VBand band)
	: TQWidget(parent), mBand(band)
{
	TQVBoxLayout *layout = new TQVBoxLayout(this,
		0, 0, "EqualizerLevel::layout");

	mSlider = new TQSlider(-200, 200, 25, 0, TQt::Vertical, this, "EqualizerLevel::mSlider");
	mSlider->setTickmarks(TQSlider::Left);
	mSlider->setTickInterval(25);
	layout->addWidget(mSlider);
	connect(mSlider, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(changed(int)));
	mLabel = new TQLabel("", this, "EqualizerLevel::mLabel");
	mLabel->setAlignment(AlignHCenter | AlignVCenter);
	layout->addWidget(mLabel);

	setMinimumHeight(200);
//	setMinimumWidth(kapp->fontMetrics().width("158kHz"));
//	setMinimumWidth(kapp->fontMetrics().width("549kHz"));

	setBand(band);

	connect(EQ, TQ_SIGNAL(modified()), TQ_SLOT(changed()));
	connect(mSlider, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(changed(int)));
}

void EqualizerLevel::setBand(VBand band)
{
	mBand = band;
	mLabel->setText(band.format());
	changed();
}

void EqualizerLevel::changed()
{
	mSlider->setValue(-mBand.level());
}

void EqualizerLevel::changed(int v)
{
	mBand.setLevel(-v);
}


///////////////////////////////////////////////
// EqualizerView

EqualizerView::EqualizerView()
	: KDialogBase(0L, "EqualizerView", false, i18n("Equalizer"), Help | Close, Close, true),
	  first(true), mWidget(0), bandsLayout(0), mPresets(0), mGoingPreset(false)
{
	mBands.setAutoDelete(true);
}

void EqualizerView::show()
{
	if (first)
	{
		first = false;
		setIcon(SmallIcon("noatun"));
		mWidget = new EqualizerWidget(this, "mWidget");
		setMainWidget(mWidget);

		bandsLayout = new TQHBoxLayout(mWidget->bandsFrame,
			0, KDialog::spacingHint(), "bandsLayout");

		connect(mWidget->preampSlider, TQ_SIGNAL(valueChanged(int)),
			this, TQ_SLOT(setPreamp(int)));
		connect(EQ, TQ_SIGNAL(preampChanged(int)),
			this, TQ_SLOT(changedPreamp(int)));

		mWidget->bandCount->setRange(EQ->minBands(), EQ->maxBands());
		connect(mWidget->bandCount, TQ_SIGNAL(valueChanged(int)),
			EQ, TQ_SLOT(setBands(int)));

		TQVBoxLayout *l = new TQVBoxLayout(mWidget->presetFrame);
		mPresets = new PresetList(mWidget->presetFrame, "mPresets");
		l->addWidget(mPresets);

		connect(mWidget->removePresetButton, TQ_SIGNAL(clicked()), TQ_SLOT(remove()));
		connect(mWidget->addPresetButton, TQ_SIGNAL(clicked()), TQ_SLOT(create()));
		connect(mWidget->resetEqButton, TQ_SIGNAL(clicked()), TQ_SLOT(reset()));

		new TDEListViewItem(mPresets, i18n("Custom"));

		connect(mPresets, TQ_SIGNAL(currentChanged(TQListViewItem*)),
			this, TQ_SLOT(select(TQListViewItem*)));

		connect(mPresets, TQ_SIGNAL(itemRenamed(TQListViewItem*)),
			this, TQ_SLOT(rename(TQListViewItem*)));

		// populate the preset list
		TQValueList<VPreset> presets = EQ->presets();
		TQValueList<VPreset>::Iterator it;
		for (it=presets.begin(); it!=presets.end(); ++it)
		{
			created(*it);
		}

		connect(EQ, TQ_SIGNAL(created(VPreset)), TQ_SLOT(created(VPreset)));
		connect(EQ, TQ_SIGNAL(renamed(VPreset)), TQ_SLOT(renamed(VPreset)));
		connect(EQ, TQ_SIGNAL(removed(VPreset)), TQ_SLOT(removed(VPreset)));

		mWidget->enabledCheckBox->setChecked(EQ->isEnabled());
		connect(mWidget->enabledCheckBox, TQ_SIGNAL(toggled(bool)),
			EQ, TQ_SLOT(setEnabled(bool)));
		connect(EQ, TQ_SIGNAL(enabled(bool)),
			mWidget->enabledCheckBox, TQ_SLOT(setChecked(bool)));

		connect(EQ, TQ_SIGNAL(changed()),
			this, TQ_SLOT(changedEq()));
		connect(EQ, TQ_SIGNAL(changedBands()),
			this, TQ_SLOT(changedBands()));

		changedBands();
		changedEq();
	} // END if(first)

	if (isVisible())
		raise();
	else
		KDialogBase::show();
}

TQListViewItem *EqualizerView::itemFor(const TQString &filename)
{
	for (TQListViewItem *i=mPresets->firstChild(); i!=0; i=i->itemBelow())
	{
		TQString t = i->text(1);
		if ((t.length()==0 && filename.length()==0) || t==filename)
			return i;
	}
	return 0;
}

TQListViewItem *EqualizerView::itemFor(const VPreset &preset)
{
	return itemFor(preset.file());
}

// why is it that when you move a TQSlider up, it goes down?
void EqualizerView::setPreamp(int x)
{
	EQ->setPreamp(-x);
}

void EqualizerView::changedPreamp(int x)
{
	mWidget->preampSlider->setValue(-x);
}


void EqualizerView::changedBands()
{
	mBands.clear();

	VEqualizer &eq = *EQ;
	for (int i=0; i < eq.bands(); ++i)
	{
		EqualizerLevel *l = new EqualizerLevel(mWidget->bandsFrame, eq[i]);
		bandsLayout->addWidget(l);
		l->show();
		mBands.append(l);
	}

	mWidget->bandCount->setValue(eq.bands());
	changedEq();
}

void EqualizerView::changedEq()
{
	if (!mGoingPreset)
	{
		TQListViewItem *customitem = itemFor("");
		if (!customitem) // this should never happen!
			return;
		mPresets->setSelected(customitem, true);
	}
}

void EqualizerView::removed(VPreset p)
{
	delete itemFor(p);
}

void EqualizerView::created(VPreset p)
{
	// store the filename in TQListViewItem::text(0)
	TQString n = p.name();
	TQString f = p.file();
	new TDEListViewItem(mPresets, n, f);
}

void EqualizerView::renamed(VPreset p)
{
	TQListViewItem *renamed = itemFor(p);
	if (!renamed) // WTF !
	{
		created(p);
		return;
	}
	renamed->setText(0, p.name());
}

void EqualizerView::remove()
{
	TQListViewItem *current=mPresets->currentItem();
	if (current->text(0)==i18n("Custom"))
		return;
	TQListViewItem *then=current->itemAbove();
	if (!then) then=current->itemBelow();

	if (then)
		mPresets->setSelected(then, true);

	VPreset p = EQ->presetByFile(current->text(1));
	p.remove();
}

void EqualizerView::create()
{
	VPreset p = EQ->createPreset(i18n("New Preset"));

	mGoingPreset = true;

	// Load the new preset
	p.load();

	// We should have just made a list view item for this preset
	// See EquailizerView::presetAdded()
	TQListViewItem *i = itemFor(p);

	if (i)
		mPresets->setSelected(i, true);

	mGoingPreset = false;
}

void EqualizerView::reset()
{
	VEqualizer &eq = *EQ;
	eq.setPreamp(0);
	for (int i=0; i < eq.bands(); ++i)
		eq.band(i).setLevel(0);

}

void EqualizerView::rename(TQListViewItem *item)
{
	EQ->presetByFile(item->text(1)).setName(item->text(0));
	item->setText(0, EQ->presetByFile(item->text(1)).name());
}

void EqualizerView::select(TQListViewItem *item)
{
	mGoingPreset = true;
	EQ->presetByFile(item->text(1)).load();
	mGoingPreset = false;
	mWidget->removePresetButton->setEnabled(item->text(1).length());
}

#undef EQ
#include "equalizerview.moc"
