/* This file is part of the KDE project
   Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <kglobal.h>
#include <klocale.h>
#include <kconfig.h>
#include <kapplication.h>
#include <kaboutdata.h>
#include <kaboutapplication.h>
#include <kdebug.h>
#include <kpopupmenu.h>
#include <kiconloader.h>

#include "mediaapplet.h"

#include "preferencesdialog.h"

extern "C"
{
	KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString configFile)
	{
		KGlobal::locale()->insertCatalogue("mediaapplet");
		return new MediaApplet(configFile, KPanelApplet::Normal,
			KPanelApplet::About | KPanelApplet::Preferences,
			parent, "mediaapplet");
	}
}

MediaApplet::MediaApplet(const QString& configFile, Type type, int actions, QWidget *parent, const char *name)
	: KPanelApplet(configFile, type, actions, parent, name)
{
	if (!parent)
		setBackgroundMode(X11ParentRelative);

	setAcceptDrops(true);
	
	loadConfig();
	mButtonList.setAutoDelete(true);

	mpDirLister = new KDirLister();

	connect( mpDirLister, SIGNAL( clear() ),
	         this, SLOT( slotClear() ) );
	connect( mpDirLister, SIGNAL( started(const KURL&) ),
	         this, SLOT( slotStarted(const KURL&) ) );
	connect( mpDirLister, SIGNAL( completed() ),
	         this, SLOT( slotCompleted() ) );
	connect( mpDirLister, SIGNAL( newItems( const KFileItemList & ) ),
	         this, SLOT( slotNewItems( const KFileItemList & ) ) );
	connect( mpDirLister, SIGNAL( deleteItem( KFileItem * ) ),
	         this, SLOT( slotDeleteItem( KFileItem * ) ) );
	connect( mpDirLister, SIGNAL( refreshItems( const KFileItemList & ) ),
	         this, SLOT( slotRefreshItems( const KFileItemList & ) ) );

	reloadList();
}

MediaApplet::~MediaApplet()
{
	delete mpDirLister;
	mButtonList.clear();
        KGlobal::locale()->removeCatalogue("mediaapplet");
}

void MediaApplet::about()
{
	KAboutData data("mediaapplet",
	                I18N_NOOP("Media Applet"),
	                "1.0",
	                I18N_NOOP("\"media:/\" ioslave frontend applet"),
	                KAboutData::License_GPL_V2,
	                "(c) 2004, Kevin Ottens");

	data.addAuthor("Kevin \'ervin\' Ottens",
	               I18N_NOOP("Maintainer"),
	               "ervin ipsquad net",
	               "http://ervin.ipsquad.net");

	data.addCredit("Joseph Wenninger",
	               I18N_NOOP("Good mentor, patient and helpful. Thanks for all!"),
	               "jowenn@kde.org");

	KAboutApplication dialog(&data);
	dialog.exec();
}

void MediaApplet::preferences()
{
	PreferencesDialog dialog(mMedia);

	dialog.setExcludedMediumTypes(mExcludedTypesList);
	dialog.setExcludedMedia(mExcludedList);

	if(dialog.exec())
	{
		mExcludedTypesList = dialog.excludedMediumTypes();
		mExcludedList = dialog.excludedMedia();
		saveConfig();
		reloadList();
	}
}

int MediaApplet::widthForHeight( int height ) const
{
	return mButtonList.count()*height;
}

int MediaApplet::heightForWidth( int width ) const
{
	return mButtonList.count()*width;
}

void MediaApplet::resizeEvent( QResizeEvent *)
{
	arrangeButtons();
}

void MediaApplet::arrangeButtons()
{
	int icon_size = 0;
	int x_offset = 0;
	int y_offset = 0;

	if(orientation() == Vertical)
	{
		icon_size = width();
		x_offset = 0;
		y_offset = icon_size;
	}
	else
	{
		icon_size = height();
		x_offset = icon_size;
		y_offset = 0;
	}

	int i = 0;
	for(MediumButton *button = mButtonList.first(); button; button = mButtonList.next())
	{
		button->resize(icon_size, icon_size);
		button->move(i*x_offset, i*y_offset);
		button->setPanelPosition(position());
		i++;
	}

	updateGeometry();
	emit updateLayout();
}

void MediaApplet::slotClear()
{
	kdDebug()<<"MediaApplet::slotClear"<<endl;

	mButtonList.clear();
	arrangeButtons();
}

void MediaApplet::slotStarted(const KURL &/*url*/)
{

}

void MediaApplet::slotCompleted()
{
	mMedia = mpDirLister->items(KDirLister::AllItems);
}

void MediaApplet::slotNewItems(const KFileItemList &entries)
{
	kdDebug()<<"MediaApplet::slotNewItems"<<endl;

	for(KFileItemListIterator it(entries); it.current(); ++it)
	{
		kdDebug() << "item: " << it.current()->url() << endl;

		bool found = false;
		for(MediumButton *button = mButtonList.first();
		    button; button = mButtonList.next())
	        {
			if(button->fileItem().url()==it.current()->url())
			{
				found = true;
				button->setFileItem(*it.current());
				break;
			}
		}
		
		if(!found && !mExcludedList.contains(it.current()->url().url()) )
		{
			MediumButton *button = new MediumButton(this, *it.current());
			button->show();
			mButtonList.append(button);
		}
	}

	arrangeButtons();
}

void MediaApplet::slotDeleteItem(KFileItem *fileItem)
{
	kdDebug()<<"MediumApplet::slotDeleteItem:"<< fileItem->url() << endl;

	for(MediumButton *button = mButtonList.first(); button; button = mButtonList.next())
	{
		if(button->fileItem().url()==fileItem->url())
		{
			mButtonList.remove(button);
			break;
		}
	}

	arrangeButtons();
}

void MediaApplet::slotRefreshItems(const KFileItemList &entries)
{
	for(KFileItemListIterator it(entries); it.current(); ++it)
	{
		kdDebug()<<"MediaApplet::slotRefreshItems:"<<(*it.current()).url().url()<<endl;

		QString mimetype = (*it.current()).mimetype();
		bool found = false;

		kdDebug()<<"mimetype="<<mimetype<<endl;

		for(MediumButton *button = mButtonList.first(); button; button = mButtonList.next())
		{
			if(button->fileItem().url()==(*it.current()).url())
			{
				if(mExcludedTypesList.contains(mimetype))
				{
					mButtonList.remove(button);
				}
				else
				{
					button->setFileItem(*it.current());
				}
				found = true;
				break;
			}
		}

		if(!found && !mExcludedTypesList.contains(mimetype) && !mExcludedList.contains(it.current()->url().url()) )
		{
			MediumButton *button = new MediumButton(this, *it.current());
			button->show();
			mButtonList.append(button);
		}
	}

	arrangeButtons();
}

void MediaApplet::positionChange(Position)
{
	arrangeButtons();
}

void MediaApplet::loadConfig()
{
	KConfig *c = config();
	c->setGroup("General");

	if(c->hasKey("ExcludedTypes"))
	{
		mExcludedTypesList = c->readListEntry("ExcludedTypes",';');
	}
	else
	{
		mExcludedTypesList.clear();
		mExcludedTypesList << "media/hdd_mounted";
		mExcludedTypesList << "media/hdd_unmounted";
		mExcludedTypesList << "media/nfs_mounted";
		mExcludedTypesList << "media/nfs_unmounted";
		mExcludedTypesList << "media/smb_mounted";
		mExcludedTypesList << "media/smb_unmounted";
	}

	if(c->hasKey("ExcludedMedia"))
	{
		mExcludedList = c->readListEntry("ExcludedMedia",';');
	}
	else
	{
		mExcludedList.clear();
	}

}

void MediaApplet::saveConfig()
{
	KConfig *c = config();
	c->setGroup("General");

	c->writeEntry("ExcludedTypes", mExcludedTypesList, ';');
	c->writeEntry("ExcludedMedia", mExcludedList, ';');

	c->sync();
}

void MediaApplet::reloadList()
{
	mpDirLister->stop();
	mButtonList.clear();
	mpDirLister->clearMimeFilter();
	mpDirLister->setMimeExcludeFilter(mExcludedTypesList);
	mpDirLister->openURL(KURL("media:/"));
}

void MediaApplet::mousePressEvent(QMouseEvent *e)
{
	if(e->button()==RightButton)
	{
		KPopupMenu menu(this);

		menu.insertTitle(i18n("Media"));
		menu.insertItem(SmallIcon("configure"), i18n("&Configure..."), 1);

		int choice = menu.exec(this->mapToGlobal(e->pos()));

		if(choice==1)
		{
			preferences();
		}
	}
}

#include "mediaapplet.moc"
