#include "effects.h"
#include "engine.h"
#include <common.h>
#include <dynamicrequest.h>
#include <artsflow.h>
#include <noatunapp.h>
#include <player.h>
#include <soundserver.h> 
#include <iostream.h>
#include "StereoEffectStack_Noatun.h"

#define engine napp->player()->engine()
#define server (*(engine->server()))
#define stack (*engine->effectStack())

using namespace Arts;

Effect::Effect(const char *name)
	: mId(0), mName(name)
{
	mEffect=new StereoEffect;
	*mEffect=DynamicCast(server.createObject(std::string(name)));
	napp->effects()->mItems.append(this);
}

long Effect::id() const
{
	return mId;
}

StereoEffect *Effect::effect() const
{
	return mEffect;
}

Effect *Effect::after() const
{
	QList<Effect> effects=napp->effects()->effects();
	QListIterator<Effect> i(effects);
	for(; i.current(); ++i)
		if ((*i)->id()==mId)
		{
			++i;
			if (*i);
				return *i;
		}

	return 0;
}

Effect *Effect::before() const
{
	QList<Effect> effects=napp->effects()->effects();
	QListIterator<Effect> i(effects);
	for(; i.current(); ++i)
		if ((*i)->id()==mId)
		{
			--i;
			if (*i);
				return *i;
		}

	return 0;
}

QCString Effect::name() const
{
	return mName;
}

QString Effect::title() const
{
	return mName.right(mName.length()-mName.findRev("::")-2);
}

bool Effect::isNull() const
{
	return effect()->isNull();
}

Effect::~Effect()
{
	napp->effects()->remove(this, false);
	emit napp->effects()->deleting(this);
	delete mEffect;
	napp->effects()->mItems.removeRef(this);
}


Effects::Effects()
{
	mItems.setAutoDelete(true);
}

bool Effects::insert(const Effect *after, Effect *item)
{
	if (!item) return false;
	if (item->id()) return false;
	if (item->isNull()) return false;
	long i;
	item->effect()->start();

	if (!after)
		i=stack.insertTop(*item->effect(), (const char*)item->name());
	else
		i=stack.insertAfter(after->id(), *item->effect(), (const char*)item->name());
	if (!i)
	{
		item->effect()->stop();
		return false;
	}
	
	item->mId=i;
	emit added(item);
	return true;
}

bool Effects::append(Effect *item)
{
	if (!item) return false;
	if (item->id()) return false;
	if (item->isNull()) return false;

	item->effect()->start();
	item->mId=stack.insertBottom(*item->effect(), (const char*)item->name());
	if (!item->mId)
	{
		item->effect()->stop();
		return false;
	}
	emit added(item);
	return true;
}

void Effects::move(const Effect *after, Effect *item)
{
	if (!item) return;
	if (!item->id()) return;
	long id=after ? after->id() : 0;
	stack.move(id, item->id());
	emit moved(item);
}

void Effects::remove(Effect *item, bool del)
{
	if (!item) return;
	if (!item->id()) return;

	stack.remove(item->id());
	item->effect()->stop();
	item->mId=0;
	removed(item);

	if (del)
		delete item;
}

void Effects::removeAll(bool del)
{
	for (QListIterator<Effect> i(mItems); i.current(); ++i)
		if ((*i)->id())
			remove(*i, del);
}

QStrList Effects::available() const
{
	QStrList val;
	Arts::TraderQuery query;
	query.supports("Interface","Arts::StereoEffect");
	vector<Arts::TraderOffer> *offers = query.query();
	for (vector<Arts::TraderOffer>::iterator i=offers->begin(); i!=offers->end(); i++)
	{
		Arts::TraderOffer &offer=*i;
		QCString name = offer.interfaceName().c_str();
		val.append(name);
	}
	delete offers;
	return val;
}

Effect *Effects::findId(long id) const
{
	for (QListIterator<Effect> i(mItems); i.current(); ++i)
		if ((*i)->id()==id)
			return *i;
	return 0;
}

QList<Effect> Effects::effects() const
{
	vector<long> *items=stack.effectList();
	QList<Effect> effects;
	for (vector<long>::iterator i=items->begin();i!=items->end();i++)
		if (Effect *e=findId(*i))
			effects.append(e);
	
	delete items;
	return effects;
}

#undef server
#undef stack
#undef engine

#include "effects.moc"
