// Copyright (c) 2003 Charles Samuels <charles@kde.org>
// See the file COPYING for redistribution terms.

#include "oblique.h"
#include "base.h"
#include "view.h"
#include "file.h"
#include "selector.h"
#include "cmodule.h"

#include <noatun/player.h>

#include <kconfig.h>
#include <kstddirs.h>

#include <qtimer.h>

extern "C" Plugin *create_plugin()
{
	return new Oblique();
}



Oblique::Oblique()
	: Playlist(0, 0), mSchemaCollection("oblique/schemas")
{
	mView = 0;
	KConfigGroup g(KGlobal::config(), "oblique");

	mFileOfQuery = g.readEntry("schema", "standard");
	if (!loadQuery(mFileOfQuery))
	{
		loadQuery("standard");
	}

	mBase = new Base(::locate("data", "noatun/")+"/oblique-list");
	mView = new View(this, &mQuery);
	connect(mView->tree(), SIGNAL(selected(TreeItem*)), SLOT(selected(TreeItem*)));

	connect(napp->player(), SIGNAL(loopTypeChange(int)), SLOT(loopTypeChange(int)));

	mSelector = new SequentialSelector(mView->tree());

	new Configure(this);

	mView->tree()->connect(mBase, SIGNAL(added(File)), SLOT(insert(File)));
	mView->tree()->connect(mBase, SIGNAL(removed(File)), SLOT(remove(File)));
	mView->tree()->connect(mBase, SIGNAL(modified(File)), SLOT(update(File)));

	// psst, window's gone, pass it on!
	connect(mView, SIGNAL(listHidden()), SIGNAL(listHidden()));
	connect(mView, SIGNAL(listShown()), SIGNAL(listShown()));

	reload();
}

void Oblique::reload()
{
	loadQuery(mFileOfQuery, true);
}


bool Oblique::loadQuery(const QString &name, bool compact)
{
	compact=false; // TODO: get compacting to work
	mFileOfQuery = name;
	if (!mQuery.load(schemaCollection().file(name, false)))
		return false;

	if (mView && mView->tree())
	{
		mView->tree()->reset();
		mDeferredLoaderAt = 1;
		mLoaderCompactorAt = 0;
		if (compact)
			mLoaderCompactorAt = 1;

		loadItemsDeferred();
	}
	return true;
}

void Oblique::loadItemsDeferred()
{
	if (mDeferredLoaderAt > mBase->high()) return;

	File f = mBase->find(mDeferredLoaderAt);
	if (mLoaderCompactorAt)
	{
		if (mLoaderCompactorAt != mDeferredLoaderAt)
		{
			if (f)
			{
				f.setId(mLoaderCompactorAt);
			}
		}
		if (f)
			mLoaderCompactorAt++;
	}

	if (f)
		mView->tree()->insert(f);
	mDeferredLoaderAt++;

	QTimer::singleShot(0, this, SLOT(loadItemsDeferred()));
}

void Oblique::loopTypeChange(int i)
{
	PlaylistItem now = current();

	if (i == Player::Random)
	{
		if (!dynamic_cast<RandomSelector*>(mSelector))
		{
			delete mSelector;
			mSelector = new RandomSelector(mView->tree());
		}
	}
	else
	{
		delete mSelector;
		mSelector = new SequentialSelector(mView->tree());
	}
}

Oblique::~Oblique()
{
	napp->player()->stop();
	delete mView;
	delete mBase;
}

void Oblique::reset()
{
	mView->tree()->setCurrent(0);
	loopTypeChange(0);
}

void Oblique::clear()
{
	mBase->clear();
}

void Oblique::addFile(const KURL &url, bool play)
{
	File f = mBase->add(url.path());
	PlaylistItem p=new Item(f);
	p.data()->added();
	if (play) setCurrent(p);
}


PlaylistItem Oblique::next()
{
	return mSelector->next();
}

PlaylistItem Oblique::previous()
{
	return mSelector->previous();
}


PlaylistItem Oblique::current()
{
	return mSelector->current();
}

void Oblique::setCurrent(const PlaylistItem &item)
{
	if (!item) return;
	mSelector->setCurrent(*static_cast<Item*>(const_cast<PlaylistItemData*>(item.data())));
	emit playCurrent();
}



PlaylistItem Oblique::getFirst() const
{
	FileId first=1;
	File item = mBase->first(first);

	if (!item) return 0;

	return new Item(item);
}


PlaylistItem Oblique::getAfter(const PlaylistItem &item) const
{
	File after = mBase->first(static_cast<const Item*>(item.data())->itemFile().id()+1);
	if (!after) return 0;
	return new Item(after);
}

bool Oblique::listVisible() const
{
	return mView->isVisible();
}

void Oblique::showList()
{
	mView->show();
}

void Oblique::hideList()
{
	mView->hide();
}


void Oblique::selected(TreeItem *cur)
{
	Item *item = new Item(cur->file());
	PlaylistItem pli = item;
	setCurrent(pli);
}


#include "oblique.moc"

