#include "UserClasses.moc"
#include "NewClass.h"
#include "EditLimit.h"
#include <klocale.h>
#include <kapplication.h>
#include <qlistbox.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qpushbutton.h>
#include <qlabel.h>
#include <qgroupbox.h>
#include <qwhatsthis.h>
#include <iostream.h>

#include <sys/types.h>
#include <grp.h>
#include <kmessagebox.h>

UserClasses::UserClasses(QWidget * parent, const char * name)
  : UserClassesBase(parent,name)
{
	ftpxs=0;
	connect(classes,SIGNAL(highlighted(const QString &)),SLOT(classSelected(const QString &)));
	QWhatsThis::add(classes, i18n("User classes can be used to control access from specific hosts/users. Use the <b>Add class</b> and <b>Delete class</b> buttons on the right of this box to add or remove classes. Use the other buttons to control the access rights of users in the class selected here."));
	QWhatsThis::add(anon,i18n("Anonymous users (login=ftp or anonymous) can belong to this class"));
	QWhatsThis::add(guest,i18n("Guest users (restricted real users) can belong to this class"));
	QWhatsThis::add(real,i18n("Real users can belong to this class"));
	QWhatsThis::add(addrs,i18n("Specify the addresses for this user class here;\nmay be globbed:\n* = any address\n*.localdomain.com = any address in localdomain.com\n127.0.0.* = IPs 127.0.0.1-127.0.0.255\n..."));
	QWhatsThis::add(lbl1,i18n("Specify the addresses for this user class here;\nmay be globbed:\n* = any address\n*.localdomain.com = any address in localdomain.com\n127.0.0.* = IPs 127.0.0.1-127.0.0.255\n..."));
	connect(newclass, SIGNAL(clicked()), SLOT(newClassPressed()));
	QWhatsThis::add(newclass, i18n("Add a new user class"));
	QWhatsThis::add(deleteclass, i18n("Delete the currently selected user class"));
	connect(deleteclass, SIGNAL(clicked()), SLOT(deleteClassPressed()));
	QWhatsThis::add(autogroup,i18n("Users from this class are automatically members\nof the group selected here.\nThat way, you can (for example) grant local users\nanonymous access to files remote users\ncan't download."));
	connect(autogroup, SIGNAL(clicked()), SLOT(autogroupSelected()));
	QWhatsThis::add(groups,i18n("Users from this class are automatically members\nof the group selected here.\nThat way, you can (for example) grant local users\nanonymous access to files remote users\ncan't download."));
	{
		group *g;
		while((g=getgrent())!=0)
			groups->insertItem(g->gr_name);
		endgrent();
	}	
	connect(groups,SIGNAL(highlighted(const QString &)),SLOT(groupSelected(const QString &)));
	QWhatsThis::add(GroupBox3, i18n("You can use limits to restrict the number of simultaneous connections of users in this class at specific times. Use the <b>Add Limit</b>, <b>Edit Limit</b> and <b>Delete Limit</b> buttons on the right to control limits."));
	QWhatsThis::add(limits, i18n("You can use limits to restrict the number of simultaneous connections of users in this class at specific times. Use the <b>Add Limit</b>, <b>Edit Limit</b> and <b>Delete Limit</b> buttons on the right to control limits."));
	connect(addLimit, SIGNAL(clicked()), SLOT(addLimitPressed()));
	connect(editLimit, SIGNAL(clicked()), SLOT(editLimitPressed()));
	connect(rmLimit, SIGNAL(clicked()), SLOT(deleteLimitPressed()));
	QWhatsThis::add(addLimit, i18n("You can use limits to restrict the number of simultaneous connections of users in this class at specific times. Use the <b>Add Limit</b>, <b>Edit Limit</b> and <b>Delete Limit</b> buttons on the right to control limits."));
	QWhatsThis::add(editLimit, i18n("You can use limits to restrict the number of simultaneous connections of users in this class at specific times. Use the <b>Add Limit</b>, <b>Edit Limit</b> and <b>Delete Limit</b> buttons on the right to control limits."));
	QWhatsThis::add(rmLimit, i18n("You can use limits to restrict the number of simultaneous connections of users in this class at specific times. Use the <b>Add Limit</b>, <b>Edit Limit</b> and <b>Delete Limit</b> buttons on the right to control limits."));
}
UserClasses::~UserClasses()
{
}
void UserClasses::redrawList()
{
	ftpclass *f=0;
	classes->clear();
	while((f=ftpxs->getNextClass(f))!=0)
		classes->insertItem(f->getName());
	classes->update();
	classes->setSelected(0,true);
	classSelected(classes->text(0));
}
void UserClasses::redrawLimits()
{
		ftpclass *c=ftpxs->seekClass(current);
		limits->clear();
		ftplimit *fl=0;
		while((fl=c->getNextLimit(fl)))
			limits->insertItem(fl->getId());
		limits->update();
}
void UserClasses::newClassPressed() // SLOT
{
	NewClass n;
	connect(&n,SIGNAL(classAdded(ftpclass *)),SLOT(classAdded(ftpclass *)));
	n.exec();
}
void UserClasses::deleteClassPressed() // SLOT
{
	// find name of selected class...
	QString name;
	for(unsigned int i=0; i<classes->count() && name==0; i++)
		if(classes->isSelected(i)) name=classes->text(i);
	if(name!=0) {
		ftpxs->removeClass(name);
		redrawList();
	}
}
void UserClasses::addLimitPressed() // SLOT
{
	if(current==0)
		KMessageBox::sorry(this, i18n("Limits are specific to user classes - create a class first."));
	else {
		EditLimit el(0, ftpxs->seekClass(current));
		connect(&el,SIGNAL(EditLimitOk(ftplimit *, ftpclass *)), SLOT(limitChanged(ftplimit *, ftpclass *)));
		el.exec();
	}
}
void UserClasses::editLimitPressed() // SLOT
{
	if(current==0)
		KMessageBox::sorry(this, i18n("Limits are specific to user classes - create a class first."));
	else {
		// Find currently selected limit...
		QString ID=QString::null;
		for(unsigned int i=0; i<limits->count() && ID==QString::null; i++)
			if(limits->isSelected(i))
				ID=limits->text(i);
		ftplimit *f=0, *thislimit=0;
		ftpclass *c=ftpxs->seekClass(current);
		if(c!=0) {
			while((f=c->getNextLimit(f)) && thislimit==0) {
				if(f->getId()==ID)
					thislimit=f;
			}
		}
		if(thislimit==0)
			KMessageBox::sorry(this, i18n("You must select a limit first."));
		else {
			EditLimit el(thislimit, ftpxs->seekClass(current));
			connect(&el,SIGNAL(EditLimitOk(ftplimit *, ftpclass *)), SLOT(limitChanged(ftplimit *, ftpclass *)));
			el.exec();
		}
	}
}
void UserClasses::deleteLimitPressed() // SLOT
{
	if(current==0)
		KMessageBox::sorry(this, i18n("Select a class first."));
	else {
// EditLimit *el;
		// Find currently selected limit...
		QString ID=QString::null;
		for(unsigned int i=0; i<limits->count() && ID==QString::null;i++)
			if(limits->isSelected(i))
				ID=limits->text(i);
		ftplimit *f=0, *thislimit=0;
		ftpclass *c=ftpxs->seekClass(current);
		if(c!=0)
			while((f=c->getNextLimit(f)) && thislimit==0)
				if(f->getId()==ID)
					thislimit=f;
		if(thislimit==0)
			KMessageBox::sorry(this, i18n("You must select a limit first."));
		else {
			c->deleteLimit(thislimit);
			redrawLimits();
		}
	}
}
void UserClasses::limitChanged(ftplimit *l, ftpclass *c) // SLOT
{
	bool	 isNewLimit=true;
	ftplimit *fl=0;
	while((fl=c->getNextLimit(fl)) && isNewLimit)
		if(fl==l)
			isNewLimit=false;
	if(isNewLimit)
		c->addLimit(l);
	if (current == c->getName()) { // We're still displaying the class this limit is for...
		redrawLimits();
		for(unsigned int i=0; i<limits->count(); i++)
			limits->setSelected(i, false);
		limits->setSelected(limits->count()-1, true);
	}
}
void UserClasses::classAdded(ftpclass *c) // SLOT
{
	update();
	ftpxs->addClass(c);
	redrawList();
	int num=0;	// select new class...
	ftpclass *f=0;
	while((f=ftpxs->getNextClass(f))!=0)
		num++;
	classes->setSelected(num-1,true);
	classSelected(c->getName());
}
void UserClasses::classDeleted(char const * const c) // SLOT
{
}

void UserClasses::groupSelected(const QString &item) // SLOT
{
	QString name=QString::null;
	if(!autogroup->isChecked())
		autogroup->setChecked(true);
	for(unsigned int i=0; i<classes->count() && name==QString::null; i++)
		if(classes->isSelected(i)) name=classes->text(i);
	if(name.isNull()) { // Theoretically, this can't happen... But apparently it happens occasionally.
		name=classes->text(0);
		classes->setSelected(0, true);
		classSelected(classes->text(0));
	}
	ftpclass *f=ftpxs->seekClass(name);
	if(f)
	  f->setAutogroup(item);
}
void UserClasses::autogroupSelected() // SLOT
{
	groups->setEnabled(autogroup->isChecked());
}
void UserClasses::classSelected(const QString &item) // SLOT
{
	ftpclass *c=0;
	ftpclass *thisclass=0;
	update();
	while((c=ftpxs->getNextClass(c))!=0 && thisclass==0)
		if(item == c->getName())
			thisclass=c;
	if(thisclass!=0) {
		anon->setChecked(thisclass->isAnon());
		guest->setChecked(thisclass->isGuest());
		real->setChecked(thisclass->isReal());
		addrs->setText(thisclass->getAddrs());
		current=thisclass->getName();
		if(thisclass->getAutogroup()==0) {
			autogroup->setChecked(false);
			groups->setEnabled(false);
		} else {
			autogroup->setChecked(true);
			groups->setEnabled(true);
			for(unsigned int i=0; i<groups->count(); i++)
				if(groups->text(i).lower() == thisclass->getAutogroup().lower())
					groups->setCurrentItem(i);
		}
		limits->clear();
		ftplimit *fl=0;
		while((fl=thisclass->getNextLimit(fl)))
			limits->insertItem(fl->getId());
	} else
		current= QString::null;
}
void UserClasses::ftpaccessLoaded(ftpaccess *xs) // SLOT
{
	ftpxs=xs;
	limits->clear();
	redrawList();
}
void UserClasses::update() // SLOT
{
	ftpclass *c=0;
	ftpclass *thisclass=0;
	if(current!=0) {	// store current changes
		while((c=ftpxs->getNextClass(c))!=0 && thisclass==0)
			if(current == c->getName())
				thisclass=c;
		if(thisclass!=0) {
			thisclass->setAnon(anon->isChecked());
			thisclass->setGuest(guest->isChecked());
			thisclass->setReal(real->isChecked());
			thisclass->setAddrs(addrs->text());
			if(autogroup->isChecked()) {
				QString gr = groups->currentText();
				thisclass->setAutogroup(gr);
			} else
				thisclass->setAutogroup(0);
		}
	}
}
