package de.uka.ipd.consensus.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import de.uka.ipd.consensus.foundation.ontology.OntologyManagerClassException;
import de.uka.ipd.consensus.foundation.ontology.OntologyManagerException;
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.AssociationRole;
import de.uka.ipd.consensus.foundation.schema.Topic;
import de.uka.ipd.consensus.foundation.schema.User;

/**
 * 
 * TODO
 * @author Thomas Much
 * @version 2006-06-14
 */
public class AssociationRoleImpl extends TM4JObjectWrapper implements AssociationRole {


	protected AssociationRoleImpl(OntologyManagerImpl omi, org.tm4j.topicmap.Member tmMember) {
		super(omi,tmMember);
	}


	protected org.tm4j.topicmap.Member getWrappedMember() {
		return (org.tm4j.topicmap.Member)this.getWrappedObject();
	}

	
	public Association getAssociation() {
		return TM4JObjectWrapper.wrap( this.getOntologyManager(), this.getWrappedMember().getParent() );
	}


	public Topic getType() {
		Object obj = TM4JObjectWrapper.wrap( this.getOntologyManager(), this.getWrappedMember().getRoleSpec() );
		if ((obj != null) && (obj instanceof Topic)) {
			return (Topic)obj;
		}
		else {
			return null;
		}
	}


	public void setType(User setter, Topic type) throws OntologyManagerException,DynamicRightsManagerException {
		if ((type != null) && this.getOntologyManager().useClasses() && !type.isClassTopic()) {
			throw new OntologyManagerClassException("Type " + type + " is not a class");
		}

		// TODO: Aufpassen, es darf immer nur ein Role-Objekt pro Typ geben, bei Wechsel Rollen-Topics evtl. mergen!
		// TODO: Assoz-Version erhöhen
	}


	public boolean isOfType(Topic type) {
		org.tm4j.topicmap.Topic tmTopic = this.getWrappedMember().getRoleSpec();
		if (type == null) {
			return (tmTopic == null);
		}
		else {
			return ((TopicImpl)type).getWrappedTopic().equals( tmTopic );
		}
	}


	public String getName() {
		Topic type = this.getType();
		if (type != null) {
			return type.getName();
		}
		else {
			return "";
		}
	}


	public Collection getTopics(User user) {
		OntologyManagerImpl  omi = this.getOntologyManager();
		DynamicRightsManager drm = omi.getDynamicRightsManager();

		Collection players = this.getWrappedMember().getPlayers();
		
		if (players == null) {
			return Collections.EMPTY_SET;
		}
		
		ArrayList list = new ArrayList(10);

		Iterator it = players.iterator();
		
		while (it.hasNext()) {
			org.tm4j.topicmap.Topic t = (org.tm4j.topicmap.Topic)it.next();
	
			if (!omi.isInternalTopicType(t)) {
				Object obj = TM4JObjectWrapper.wrap( omi, t );

				if ((obj instanceof Topic) && ((drm == null) || drm.mayViewTopic( user, (Topic)obj ))) {
					list.add( obj );
				}
			}
		}
		
		Collections.sort( list );

		return Collections.unmodifiableCollection( list );
		
//		Collection c = this.getWrappedMember().getPlayers();
//		return TM4JCollectionWrapperSet.getInstance( this.getOntologyManager(), c );
	}


	public void addTopic(User adder, Topic topic) throws OntologyManagerException,DynamicRightsManagerException {
		try {
			this.getWrappedMember().addPlayer( ((TopicImpl)topic).getWrappedTopic() );
			((AssociationImpl)this.getAssociation()).incVersion();
			if (adder != null) {
				this.getOntologyManager().fireAssociationTopicAdded( this.getAssociation(), adder, topic );
			}
		}
		catch (Exception e) {
			throw new OntologyManagerException( e );
		}
	}


	public void removeTopic(User remover, Topic topic) throws OntologyManagerException, DynamicRightsManagerException {
		try {
			this.getWrappedMember().removePlayer( ((TopicImpl)topic).getWrappedTopic() );
			((AssociationImpl)this.getAssociation()).incVersion();
			if (remover != null) {
				this.getOntologyManager().fireAssociationTopicRemoved( this.getAssociation(), remover, topic );
			}
		}
		catch (Exception e) {
			throw new OntologyManagerException( e );
		}
	}


	public boolean hasTopic(Topic topic) {
		if (topic != null) {
			Collection c = this.getWrappedMember().getPlayers();
			if (c != null) {
				Iterator it = c.iterator();
				while (it.hasNext()) {
					org.tm4j.topicmap.Topic tmTopic = (org.tm4j.topicmap.Topic)it.next();
					
					if (tmTopic.equals( ((TopicImpl)topic).getWrappedTopic() )) {
						return true;
					}
				}
			}
		}
		return false;
	}


	public int compareTo(Object other) {
		return this.getName().toLowerCase().compareTo( ((AssociationRoleImpl)other).getName().toLowerCase() );
	}


	public String toString() {
		String s = this.getName();
		return "AssociationRole " + (s.length() > 0 ? ("\"" + s + "\""): "(untyped)");
	}
	
}
