/*
 * This file is part of DesktopBSD, see the README file.
 *
 * Authors: Reinhard Pointner
 *			 Peter Hofer <ph@desktopbsd.net>
 *			 (C) 2004, 2005
 *
 * Copyright: BSD, see the COPYING file included in this distribution
 *
 */

#include <user.h>
#include <users.h>
#include <frmadduser.h>
#include <frmchangepasswd.h>

/* DesktopBSD */
#include <dbsdglobal.h>
#include <dialogs.h>

/* Qt */
#include <qregexp.h>
#include <qstring.h>
#include <qstringlist.h>

#define CMBPERM_USER 0
#define CMBPERM_MOUNT 1
#define CMBPERM_ADMINISTRATOR 2

void modUsers::initModule() {
	showSystemUsers = false;
	users.setAutoDelete(true);
	refreshUserList();
}

void modUsers::showUser(QListBoxItem *item) {
	User  *user = users[item];
	if(user == NULL) {
		Dialogs::warnDlg(tr("Error: %1 doesn't exist (?)").arg(item->text()));
		return;
	}

	lblUsername->setText(user->getUsername());
	lblComment->setText(user->getComment());

	if(user->isMemberOf("wheel"))
		cmbPermissions->setCurrentItem(CMBPERM_ADMINISTRATOR);
	else if(user->isMemberOf("mount"))
		cmbPermissions->setCurrentItem(CMBPERM_MOUNT);
	else
		cmbPermissions->setCurrentItem(CMBPERM_USER);

	bool locked = user->isLocked();
	lblLocked->setText(tr("Status: <b>%1</b>").arg(locked ? tr("Locked") : tr("Not locked")));
	btnLockUnlock->setText(locked ? tr("Unlock") : tr("Lock"));
	pixLocked->setPixmap(DBSDGlobal::getIconLoader()->loadIcon(locked ? "encrypted" : "decrypted", DBSDIconLoader::Size16x16));
}


void modUsers::refreshUserList() {
	QPtrList<User>  pwUsers = Users::getAllUsers();
	if(pwUsers.isEmpty()) {
		Dialogs::warnDlg(tr("No users found."));
		return;
	}

	users.clear();
	lstUsers->clear();

	User  *user;
	while((user = pwUsers.first()) != NULL) {
		if(showSystemUsers || (user->getUID() >= 1000 && user->getUID() < 65534)) {
			lstUsers->insertItem(user->getUsername(), 0);
			users.insert(lstUsers->item(0), user);

			pwUsers.take();
		} else
			delete pwUsers.take();
	}

	lstUsers->sort();
	lstUsers->setSelected(0, true);
}


void modUsers::addUser() {
	frmAddUser dlg(this);
	dlg.exec();

	refreshUserList();
	selectUser(dlg.getUsername());
}


void modUsers::deleteUser() {
	if (checkSelection()) {
		User  *user = users[lstUsers->selectedItem()];
		if(Dialogs::question(tr("Delete '%1'?").arg(user->getUsername()))) {
			bool  rmHome = Dialogs::question(tr("Also remove user's home directory and contents?"));
			if(!Users::removeUser(*user, rmHome))
				Dialogs::warnDlg(tr("An error occured when removing the user."));

			refreshUserList();
		}
	}
}


void modUsers::changePasswd() {
	if (checkSelection()) {
		User  *user = users[lstUsers->selectedItem()];
		frmChangePasswd  dlg(this, NULL, true);
		dlg.setUser(*user);
		dlg.exec();
	}
}

bool modUsers::checkSelection() {
	bool	selected = (lstUsers->selectedItem() != NULL);

	if(!selected)
		Dialogs::infoDlg(tr("No User selected."));

	return  selected;
}


void modUsers::init() {
/* DesktopBSD permission settings require a
 * special set of groups.
 *
 * We can't make sure these groups exist and have
 * proper rights, so we hide this from the user.
 */
	if(!DBSDGlobal::isNativeDesktopBSD())
		grpPermissions->hide();

	/* Initialize Graphics */
	DBSDIconLoader  *iloader = DBSDGlobal::getIconLoader();

	btnAdd->setIconSet(iloader->loadIcon("filenew", DBSDIconLoader::Button));
	btnDel->setIconSet(iloader->loadIcon("editdelete", DBSDIconLoader::Button));
	btnSetComment->setIconSet(iloader->loadIcon("txt", DBSDIconLoader::Button));
	btnChangePasswd->setIconSet(iloader->loadIcon("password", DBSDIconLoader::Button));
	btnChangeRootPasswd->setIconSet(iloader->loadIcon("password", DBSDIconLoader::Button));
	pixUser->setPixmap(iloader->loadIcon("personal", DBSDIconLoader::Size32x32));
}


void modUsers::setComment() {
	if (checkSelection()) {
		User		*user = users[lstUsers->selectedItem()];
		QString	name = user->getUsername();

		bool		ok;
		QString	comment;
		QRegExp	commExpr("(\\w|\\s)+");

		for(;;) {
			comment = Dialogs::strInput(tr("Enter %1's new full name:").arg(name), &ok, user->getComment());

			if(ok  &&  !commExpr.exactMatch(comment)) {
				Dialogs::infoDlg(tr("Please don't use other characters than letters and numbers."));
				continue;
			}

			break;
		}


		if(ok) {
			if(user->setComment(comment)) {
				refreshUserList();
				selectUser(name);
			} else
				Dialogs::warnDlg(tr("Setting %1's full name failed.").arg(name));
		}
	}
}


bool modUsers::selectUser(const QString  & user) {
	QListBoxItem  *li = lstUsers->findItem(user, Qt::ExactMatch);
	if(li != NULL)
		lstUsers->setSelected(li, true);

	return (li != NULL);
}


void modUsers::lockUnlockUser() {
	if (checkSelection()) {
		User  *user = users[lstUsers->selectedItem()];
		if(user->isLocked())
			user->unlock();
		else
			user->lock();

		showUser(lstUsers->selectedItem());
	}
}



void modUsers::permissionChanged(int perm) {
	if (checkSelection()) {
		QListBoxItem *lbi = lstUsers->selectedItem();

		QString uname = lbi->text();
		if(uname == getenv("KDESU_USER") || uname == "root") {
			Dialogs::warnDlg(tr("You can't change your own permissions."));
			showUser(lstUsers->selectedItem());
			return;
		}

		User  *user = users[lbi];
		QStringList  grpMemberships = user->getGroupMemberships();

		if(perm == CMBPERM_ADMINISTRATOR) {
			grpMemberships.append("wheel");
			grpMemberships.append("mount");
		} else if(perm == CMBPERM_MOUNT) {
			grpMemberships.remove("wheel");
			grpMemberships.append("mount");
		} else {
			grpMemberships.remove("wheel");
			grpMemberships.remove("mount");
		}

		if(!user->setGroupMemberships(grpMemberships)) {
			Dialogs::warnDlg(tr("Changing this user's permissions failed."));
			showUser(lstUsers->selectedItem());
		} else
			Dialogs::infoDlg(tr("This user's permissions were changed.\n"
									  "\n"
									  "The changes will take effect the next time\n"
									  "the user logs in."));
	}
}


void modUsers::changeRootPasswd() {
	User  *user = Users::getUser("root");
	if(user != NULL) {
		frmChangePasswd  dlg(this, NULL, true);
		dlg.setUser(*user);
		dlg.exec();
	}
}
