package de.uka.ipd.consensus.impl;

import java.util.Properties;

import de.uka.ipd.consensus.foundation.AbstractConsensusFoundationModule;
import de.uka.ipd.consensus.foundation.ConsensusFoundationManager;
import de.uka.ipd.consensus.foundation.logging.LoggingManager;
import de.uka.ipd.consensus.foundation.ontology.OntologyManager;
import de.uka.ipd.consensus.foundation.rights.DynamicRightsManager;
import de.uka.ipd.consensus.foundation.rights.DynamicRightsManagerException;
import de.uka.ipd.consensus.foundation.schema.Association;
import de.uka.ipd.consensus.foundation.schema.Attribute;
import de.uka.ipd.consensus.foundation.schema.Attributeable;
import de.uka.ipd.consensus.foundation.schema.Concept;
import de.uka.ipd.consensus.foundation.schema.Rateable;
import de.uka.ipd.consensus.foundation.schema.Rating;
import de.uka.ipd.consensus.foundation.schema.SuperSubclass;
import de.uka.ipd.consensus.foundation.schema.Synonym;
import de.uka.ipd.consensus.foundation.schema.Topic;
import de.uka.ipd.consensus.foundation.schema.TypeInstance;
import de.uka.ipd.consensus.foundation.schema.User;
import de.uka.ipd.consensus.foundation.scoring.IncentiveManager;
import de.uka.ipd.consensus.foundation.scoring.ScoringEvent;
import de.uka.ipd.consensus.foundation.scoring.ScoringListener;
import de.uka.ipd.consensus.foundation.user.UserManager;

/**
 * TODO
 * @author Thomas Much
 * @version 2006-06-14
 */
public class DynamicRightsManagerImpl extends AbstractConsensusFoundationModule implements DynamicRightsManager,ScoringListener {

	private boolean running   = false;
	private boolean typedOnly = false;

	
	public void init(Properties config, LoggingManager logging, UserManager users, OntologyManager ontology, IncentiveManager incentive) throws Exception {
		this.running = true;
		
		String typed = config.getProperty("cfimpl.dynrights.typedonly");

		this.typedOnly = Boolean.valueOf(typed).booleanValue();

		logging.debug("DynamicRightsManager init done.");
	}


	public void initCompleted(Properties config, ConsensusFoundationManager cfm) throws Exception {
		super.initCompleted(config, cfm);

		IncentiveManager im = cfm.getIncentiveManager();
		
		if (im != null) {
			im.addScoringListener( this );
		}
		
		cfm.getLoggingManager().debug("DynamicRightsManager initCompleted done.");
	}


	public void shutdown() {
		if (running) {
			running = false;
			getLoggingManager().debug("DynamicRightsManager shutdown...");
		}
	}


	public boolean mayCreateTopic(User user, Topic type) {
		if ((type == null) && (typedOnly)) {
			return (user != null) && user.isAdmin();
		}
		else {
			return true;
		}
	}


	public boolean mayCreateClassTopic(User user, Topic cls) {
		return this.mayCreateTopic( user, cls );
	}
	

	public boolean mayViewTopic(User user, Topic topic) {
		return true;
	}
	
	
	public boolean mayDeleteTopic(User user, Topic topic) {
		return ((user == null) || user.isAdmin() || (user.equals( topic.getCreator() )));
	}


	public boolean mayMergeTopics(User user, Topic topic1, Topic topic2) {
		return ((user == null) || user.isAdmin());
	}

	
	public boolean mayCreateAssociation(User user, Topic type) {
		if ((type == null) && (typedOnly)) {
			return (user != null) && user.isAdmin();
		}
		else {
			return true;
		}
	}
	
	
	public boolean mayViewAssociation(User user, Association assoc) {
		return true;
	}
	
	
	public boolean mayChangeAssociation(User user, Association assoc) {
		return true;
	}
	
	
	public boolean mayDeleteAssociation(User user, Association assoc) {
		return ((user == null) || user.isAdmin() || (user.equals( assoc.getCreator() )));
	}


	public boolean mayCreateAttribute(User user, Topic type) {
		if ((type == null) && (typedOnly)) {
			return (user != null) && user.isAdmin();
		}
		else {
			return true;
		}
	}


	public boolean mayViewAttribute(User user, Attribute attr) {
		return true;
	}


	public boolean mayAddAttribute(User user, Attribute attr, Attributeable attributeable) {
		return true;
	}


	public boolean mayChangeAttributeValue(User user, Attribute attr) {
		return true;
	}


	public boolean mayRemoveAttribute(User user, Attribute attr) {
		return true;
	}


	public boolean mayCreateRating(User user) {
		return true;
	}


	public boolean mayChangeConceptComment(User user, Concept concept) {
		return true;
	}


	public boolean mayChangeUserComment(User user, User commentated) {
		return (user != null) && (user.isAdmin() || user.equals( commentated ));
	}


	public boolean mayChangeOccurrence(User user) {
		return true;
	}


	public boolean mayAddRating(Rating rating, Rateable rateable) {
		return true;
	}


	public boolean mayRemoveRating(User remover, Rating rating) {
		return (remover != null) && (rating != null) && (remover.isAdmin() || (rating.getCreator().equals( remover )));
	}
	
	
	public boolean mayAddSynonym(User user, Topic base) {
		return true;
	}


	public boolean mayRemoveSynonym(User user, Synonym synonym) {
		return true;
	}

	
	public boolean mayAddType(User user, Topic base) {
		return true;
	}
	
	
	public boolean mayRemoveType(User user, TypeInstance type) {
		return true;
	}
	
	
	public boolean mayAddClass(User user, Topic base) {
		return true;
	}
	
	
	public boolean mayRemoveClass(User user, SuperSubclass cls) {
		return true;
	}

	
	public boolean mayQuery(User user, String query) {
		return (user != null) && user.isAdmin();
	}


	public void checkCreateTopic(User user, Topic type) throws DynamicRightsManagerException {
		if (!mayCreateTopic( user, type )) {
			if (type == null) {
				throw new DynamicRightsManagerException( user + " is not allowed to create a topic without type." );
			}
			else {
				throw new DynamicRightsManagerException( user + " is not allowed to create a topic of type " + type + "." );
			}
		}
	}
	
	
	public void checkCreateClassTopic(User user, Topic cls) throws DynamicRightsManagerException {
		if (!mayCreateClassTopic( user, cls )) {
			if (cls == null) {
				throw new DynamicRightsManagerException( user + " is not allowed to create a topic without superclass." );
			}
			else {
				throw new DynamicRightsManagerException( user + " is not allowed to create a topic with superclass " + cls + "." );
			}
		}
	}


	public void checkViewTopic(User user, Topic topic) throws DynamicRightsManagerException {
		if (!mayViewTopic( user, topic )) {
			throw new DynamicRightsManagerException( user + " is not allowed to view the topic." );
		}
	}
	
	
	public void checkDeleteTopic(User user, Topic topic) throws DynamicRightsManagerException {
		if (!mayDeleteTopic( user, topic )) {
			throw new DynamicRightsManagerException( user + " is not allowed to delete " + topic );
		}
	}
	
	
	public void checkMergeTopics(User user, Topic topic1, Topic topic2) throws DynamicRightsManagerException {
		if (!mayMergeTopics( user, topic1, topic2 )) {
			throw new DynamicRightsManagerException( user + " is not allowed to merge " + topic1 + " and " + topic2 );
		}
	}


	public void checkCreateAssociation(User user, Topic type) throws DynamicRightsManagerException {
		if (!mayCreateAssociation( user, type )) {
			if (type == null) {
				throw new DynamicRightsManagerException( user + " is not allowed to create an association without type." );
			}
			else {
				throw new DynamicRightsManagerException( user + " is not allowed to create an association of type " + type + "." );
			}
		}
	}
	
	
	public void checkViewAssociation(User user, Association assoc) throws DynamicRightsManagerException {
		if (!mayViewAssociation( user, assoc )) {
			throw new DynamicRightsManagerException( user + " is not allowed to view the association." );
		}
	}


	public void checkChangeAssociation(User user, Association assoc) throws DynamicRightsManagerException {
		if (!mayChangeAssociation( user, assoc )) {
			throw new DynamicRightsManagerException( user + " is not allowed to change " + assoc );
		}
	}
	
	
	public void checkDeleteAssociation(User user, Association assoc) throws DynamicRightsManagerException {
		if (!mayDeleteAssociation( user, assoc )) {
			throw new DynamicRightsManagerException( user + " is not allowed to delete " + assoc );
		}
	}


	public void checkCreateAttribute(User user, Topic type) throws DynamicRightsManagerException {
		if (!mayCreateAttribute( user, type )) {
			if (type == null) {
				throw new DynamicRightsManagerException( user + " is not allowed to create an attribute without type." );
			}
			else {
				throw new DynamicRightsManagerException( user + " is not allowed to create an attribute of type " + type + "." );
			}
		}
	}


	public void checkViewAttribute(User user, Attribute attr) throws DynamicRightsManagerException {
		if (!mayViewAttribute( user, attr )) {
			throw new DynamicRightsManagerException( user + " is not allowed to view the attribute." );
		}
	}


	public void checkAddAttribute(User user, Attribute attr, Attributeable attributeable) throws DynamicRightsManagerException {
		if (!mayAddAttribute( user, attr, attributeable )) {
			throw new DynamicRightsManagerException( user + " is not allowed to add " + attr + " to " + attributeable );
		}
	}


	public void checkChangeAttributeValue(User user, Attribute attr) throws DynamicRightsManagerException {
		if (!mayChangeAttributeValue( user, attr )) {
			throw new DynamicRightsManagerException( user + " is not allowed to change " + attr );
		}
	}


	public void checkRemoveAttribute(User user, Attribute attr) throws DynamicRightsManagerException {
		if (!mayRemoveAttribute( user, attr )) {
			throw new DynamicRightsManagerException( user + " is not allowed to remove " + attr );
		}
	}


	public void checkCreateRating(User user) throws DynamicRightsManagerException {
		if (!mayCreateRating( user )) {
			throw new DynamicRightsManagerException( user + " is not allowed to create ratings." );
		}
	}


	public void checkAddRating(Rating rating, Rateable rateable) throws DynamicRightsManagerException {
		if (!mayAddRating( rating, rateable )) {
			throw new DynamicRightsManagerException( rating.getCreator() + " is not allowed to add a rating to " + rateable + "." );
		}
	}


	public void checkRemoveRating(User remover, Rating rating) throws DynamicRightsManagerException {
		if (!mayRemoveRating( remover, rating )) {
			throw new DynamicRightsManagerException( remover + " is not allowed to remove a rating from " + rating.getRateable() + "." );
		}
	}

	
	public void checkChangeConceptComment(User user, Concept concept) throws DynamicRightsManagerException {
		if (!mayChangeConceptComment( user, concept )) {
			throw new DynamicRightsManagerException( user + " is not allowed to change comment for " + concept );
		}
	}


	public void checkChangeUserComment(User user, User commentated) throws DynamicRightsManagerException {
		if (!mayChangeUserComment( user, commentated )) {
			throw new DynamicRightsManagerException( user + " is not allowed to change comment for " + commentated );
		}
	}
	
	
	public void checkChangeOccurrence(User user) throws DynamicRightsManagerException {
		if (!mayChangeOccurrence( user )) {
			throw new DynamicRightsManagerException( user + " is not allowed to change occurrences." );
		}
	}
	
	
	public void checkAddSynonym(User user, Topic base) throws DynamicRightsManagerException {
		if (!mayAddSynonym( user, base )) {
			throw new DynamicRightsManagerException( user + " is not allowed to add synonyms to " + base );
		}
	}
	
	
	public void checkRemoveSynonym(User user, Synonym synonym) throws DynamicRightsManagerException {
		if (!mayRemoveSynonym( user, synonym )) {
			throw new DynamicRightsManagerException( user + " is not allowed to remove " + synonym );
		}
	}

	
	public void checkAddType(User user, Topic base) throws DynamicRightsManagerException {
		if (!mayAddType( user, base )) {
			throw new DynamicRightsManagerException( user + " is not allowed to add a type to " + base );
		}
	}
	
	
	public void checkRemoveType(User user, TypeInstance type) throws DynamicRightsManagerException {
		if (!mayRemoveType( user, type )) {
			throw new DynamicRightsManagerException( user + " is not allowed to remove " + type );
		}
	}
	

	public void checkAddClass(User user, Topic base) throws DynamicRightsManagerException {
		if (!mayAddClass( user, base )) {
			throw new DynamicRightsManagerException( user + " is not allowed to add a superclass to " + base );
		}
	}
	
	
	public void checkRemoveClass(User user, SuperSubclass cls) throws DynamicRightsManagerException {
		if (!mayRemoveClass( user, cls )) {
			throw new DynamicRightsManagerException( user + " is not allowed to remove " + cls );
		}
	}
	
	
	public void checkQuery(User user, String query) throws DynamicRightsManagerException {
		if (!mayQuery( user, query )) {
			throw new DynamicRightsManagerException( user + " is not allowed to execute query \"" + query + "\"." );
		}
	}


	public void score(ScoringEvent event) { }


	public void scored(ScoringEvent event) {
		// after the user has been scored, the DynamicRightsManager could recalculate the user's rights here
	}


	public String getVersion() {
		return "2006-06-14 tm (" + this.getClass().getName() + ")";
	}

}
