package net.sourceforge.jsurveyor;

import java.util.*;

/**
 * Class that handles privilegies for the User class. 
 * If the User, which is assigned an instance of
 * this class, is a questionnaire administrator, AccessControl also keeps track of the UserGroups
 * this User can deploy questionnaires for.
 * 
 * @version 1.0
 * @author Claus Methmann Christensen
 * @author Anders Spliid Hansen
 * @author Esben Iversen Hansen
 * @author Lars H Jensen
 * @author Marcus Overheu
 * @author Thomas Ramdal
 * @author Peter Thomsen
 */
public class AccessControl {

	/**
	 * Field LVL_ZERO
	 * The highest level of usertype
	 */
	static final String LVL_ZERO = "root";
	/**
	 * Field LVL_ONE
	 * The second-highest level of usertype
	 */
	static final String LVL_ONE = "admin";
	/**
	 * Field LVL_TWO
	 * The lowest level of usertype
	 */
	static final String LVL_TWO = "normal";

	/** 
	 * Field userType
	 * userType must be either normal, admin or root
	 * normal = regular user with no extra permissions
	 * admin = user with permissions to creater Questionnaires
	 * root = superuser with permission to make creater other users of all levels 
	 */
	private String userType;
	/**
	 * Field refAdminUserGroup
	 * Holds information about which userGroups this user that have answering his questionnaire
	 */
	private ArrayList refAdminUserGroup;

	/**
	 * Constructor that sets the userType, use this for new objects. 
	 * @pre input must be either "normal", "admin" or "root"
	 * @param userType String
	 * */
	public AccessControl(String userType) {
		assert(
			userType.equals(LVL_TWO)
				|| userType.equals(LVL_ONE)
				|| userType.equals(LVL_ZERO)) : "illegal value sent as argument";
		this.userType = userType;
		refAdminUserGroup = new ArrayList();
		assert(
			userType.equals(LVL_TWO)
				|| userType.equals(LVL_ONE)
				|| userType.equals(LVL_ZERO)) : "illegal value stored in userType";
	}

	/**
	 * Constructor that sets all attributes, only for use through DataAccess
	 * @pre userType must be either "normal", "admin" or "root"
	 * @pre adminUserGroup must contain toString representation of UserGroup objects
	 * @param userType String
	 * @param adminUserGroup ArrayList
	 */
	public AccessControl(String userType, ArrayList adminUserGroup) {
		assert(
			userType.equals(LVL_TWO)
				|| userType.equals(LVL_ONE)
				|| userType.equals(LVL_ZERO)) : "illegal value sent as argument";
		this.userType = userType;
		this.refAdminUserGroup = adminUserGroup;
		assert(
			userType.equals(LVL_TWO)
				|| userType.equals(LVL_ONE)
				|| userType.equals(LVL_ZERO)) : "illegal value stored in userType";
	}

	/** 
	 * Sets the userType.
	 * @pre input must be either "normal", "admin" or "root" 
	 * @param userType String
	 */
	public void setUserType(String userType) {
		assert(
			userType.equals(LVL_TWO)
				|| userType.equals(LVL_ONE)
				|| userType.equals(LVL_ZERO)) : "illigal value sent as argument";
		this.userType = userType;
		assert(
			userType.equals(LVL_TWO)
				|| userType.equals(LVL_ONE)
				|| userType.equals(LVL_ZERO)) : "illegal value stored in userType";
	}

	/**  
	 * Returns the userType
	 * @post return value is either "normal", "admin" or "root"
	 * @return String
	 */
	public String getUserType() {
		return userType;
	}

	/** 
	 * Adds a userGroup 
	 * @pre userType = "admin"
	 * @pre input userGroup must not be in Arraylist adminUserGroup
	 * @post toString representation of the userGroup has been added
	 * @param userGroup UserGroup
	 */
	public void addAdminUserGroup(UserGroup userGroup) {
		assert userType.equals(
			LVL_ONE) : "This method can only be used when userType is "
			+ LVL_ONE;
		assert !isAdminForUserGroup(userGroup) : "Dont add "
			+ LVL_ONE
			+ " priviliges of a group for which "
			+ LVL_ONE
			+ " priviliges has already been given";
		refAdminUserGroup.add(userGroup.toString());
	}

	/**
	 * Checks if the userGroup is added.
	 * @post returns true if the userGroup is added, otherwise false.
	 * @param userGroup UserGroup
	 * @return boolean
	 */
	private boolean isAdminForUserGroup(UserGroup userGroup) {
		return refAdminUserGroup.indexOf(userGroup.toString()) != -1;
	}

	/** 
	 * Removes a usergroup from the list.
	 * @pre userType = "admin"
	 * @pre input userGroup must be added.
	 * @post userGroup is removed
	 * @param userGroup UserGroup
	 */
	public void removeAdminUserGroup(UserGroup userGroup) {
		assert userType.equals(
			LVL_ONE) : "This method can only be used when userType is "
			+ LVL_ONE;
		assert isAdminForUserGroup(userGroup) : "You cannot remove "
			+ LVL_ONE
			+ " priviliges for a User where he doesn't have any";
		refAdminUserGroup.remove(
			refAdminUserGroup.indexOf(userGroup.toString()));
	}

	/**
	 * Retrieves the ArrayList of added userGroups.
	 * @return ArrayList
	 */
	public ArrayList getAdminUserGroup() {
		return refAdminUserGroup;
	}

	/**
	 * Returns a string representation of the object.
	 * @return String
	 */
	public String toString() {
		return "AccessControl[" + userType + "," + refAdminUserGroup + "]";
	}
}
