package net.grcomputing.opencms.webusers.lite;

import com.opencms.flex.jsp.CmsJspActionElement;
import com.opencms.file.CmsObject;
import com.opencms.file.CmsUser;
import com.opencms.core.CmsException;

import java.util.Hashtable;

/**
* <p>
* This file is part of GRC's OpenCMS module library.
* </p>
* <p>
* GRC's OpenCMS module library 
* is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* </p>
* <p>
* GRC's OpenCMS module 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 General Public License for more details.
* </p>
* <p>
* You should have received a copy of the GNU General Public License
* along with GRC's OpenCMS module library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
* Or view the license online at http://www.gnu.org/licenses/gpl.html
* </p>
* <hr>
* <p>This class provides a convenient access layer for CmsWebUser's.</p>
* <p>For the most part, this is designed to be used from JSP pages.
* In the future, I may try to implement the bean interface, but because of
* it's firm dependencies on other objects, I've not done it that way yet.</p>
* 
* @author Matt Butcher mbutcher@grcomputing.net
* @see <a href="http://grcomputing.net">http://grcomputing.net</a>
*/
public class WebUserLite {

	private CmsObject cmso = null;
	private PasswordChecker pwc = new PasswordChecker();

	/**
	 * We need to get a CmsObject to deal with the CmsUser information.
	 * So, implementing classes need to provide the default constructor
	 * with a way to get that information.
	 */
	protected WebUserLite() {

	}

	/**
	 * Create a new instance of WebUserLite. This instance may be used for
	 * adding, modifying, or retrieving information about webusers.
	 */
	public WebUserLite(CmsJspActionElement cms) {
		this.cmso = cms.getCmsObject();
	}

	/**
	 * Add a new Webuser. This method checks the new webuser and then attempts
	 * to add the user to the database.
	 * In terms of checks, this class will:
	 * <ul>
	 * <li>Check that the new username is unique</li>
	 * <li>Verify the password according to the restraints in 
	 *    the PasswordChecker</li>
	 * </ul>
	 * @param String name - username
	 * @param String group - default group
	 * @param String password - password
	 * @param String password_again - password again for validation
	 * @param String description - user description
	 * @param Hashtable info - other info that will be written into the table
	 * @return CmsUser - newly created user
	 */
	public CmsUser addWebUser(String name, String group, String password, 
		String password_again, String description, Hashtable info) 
		throws CmsException
	{
		int flags = cmso.C_FLAG_ENABLED;

		if(checkWebUserName(name))
			throw new CmsException("Username " + name + " is already in use.");
		if(!pwc.runTests(password, password_again)) 
			throw new CmsException("Invalid Password: "+ pwc.getReason());

		// Create new user
		CmsUser user = 
			cmso.addWebUser(name, password, group, description, info, flags);
		return user;
	}

	/**
	 * Add a new Webuser. This method checks the new webuser and then attempts
	 * to add the user to the database. 
	 * In terms of checks, this class will:
	 * <ul>
	 * <li>Check that the new username is unique</li>
	 * <li>Verify the password according to the restraints in 
	 *    the PasswordChecker</li>
	 * </ul>
	 * @param String name - username
	 * @param String group - default group
	 * @param String password - password
	 * @param String password_again - password again for validation
	 * @param String description - user description
	 * @param String fname - first name
	 * @param String lname - last name
	 * @param String email - email address
	 * @param Hashtable info - other info that will be written into the table
	 * @return CmsUser - newly created user
	 */
	public CmsUser addWebUser(String name, String group, String password, 
		String password_again, String description, 
		String fname, String lname, String email, Hashtable info) 
		throws CmsException
	{
		CmsUser u = addWebUser(name, group, password, 
			password_again, description, info);
		u.setFirstname(fname);
		u.setLastname(lname);
		u.setEmail(email); 
        cmso.writeWebUser(u);
		return u;
	}
	/**
	 * Check a name to see if it is used (true) or unused (false). The
	 * addWebUser methods do this automatically, and throw an exception if 
	 * the name is taken, but you may use this method explicitely to avoid the 
	 * exception handling. <b>Currently, this method always returns false</b>
	 * @param String username
	 */
	public boolean checkWebUserName(String username) {
		// For some reason, cmso.readUser() is causing probs, even when
	 	// called by an admin.
		// MPB -- I think this is fixed. Looks like there was a NPE in the
		// JSP.
		//return false;
		boolean userExists = true;
		try {
			cmso.readUser(username); 
		} catch (com.opencms.core.CmsException cmse) {
			// This means that there is no such user... and that's good.
			userExists = false;
		}
		return userExists;
	}

	/** 
	 * Performs a  number of password checks on a password to make sure that
	 * it is valid. AddWebUser does this anyway and throws an exception if 
	 * something fails, but this is a way to do the test w/o having to handle
	 * the exception.
	 * 
	 * @param password - new password
	 * @param password_again - new password again (for equality tests)
	 * @return empty String if valid, otherwise an error message.
	 */
	public String passwordCheck(String password,
		String password_again) 
	{
		if(!pwc.runTests(password, password_again)) return pwc.getReason();
		return "";
	}

	/**
	 * Manually set the PasswordChecker that will be used. If none is set,
	 * a PasswordChecker will be instantiated.
	 * @param PasswordChecker pwc
	 */
	public void setPasswordChecker(PasswordChecker pwc) {
		this.pwc = pwc;
		return;
	}

	/**
	 * returns the password checker that is to be used.
	 * @return PasswordChecker 
	 */
	public PasswordChecker getPasswordChecker() {
		return pwc;
	}

	/**
	 * Returns a CmsUser with the specified username. If no  CmsUser with that 
	 * username is found, a CmsException will be thrown. Note that this may 
	 * return a non-webuser. In general, you should probably use the 
	 * getWebUser methods, lest you get security violations.
	 */
	public CmsUser getUser(String username) throws CmsException {
		return cmso.readUser(username); 
	}

	/**
	 * Returns a CmsUser with the specified username. If no CmsUser with that 
	 * username is found, a CmsException will be thrown. Note that this will 
	 * always return a webuser.
	 */
	public CmsUser getWebUser(String username) throws CmsException {
		return cmso.readWebUser(username); 
	}
}
