package de.uka.ipd.consensus.impl;

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.rating.RatingManager;
import de.uka.ipd.consensus.foundation.rating.RatingManagerException;
import de.uka.ipd.consensus.foundation.rights.DynamicRightsManager;
import de.uka.ipd.consensus.foundation.rights.DynamicRightsManagerException;
import de.uka.ipd.consensus.foundation.schema.Attribute;
import de.uka.ipd.consensus.foundation.schema.Attributeable;
import de.uka.ipd.consensus.foundation.schema.Rating;
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 AttributeImpl extends TM4JTopicWrapper implements Attribute {


	protected AttributeImpl(OntologyManagerImpl omi, org.tm4j.topicmap.Topic tmTopic) {
		super(omi,tmTopic);
	}


	public String getValue() {
		org.tm4j.topicmap.Occurrence occ = this.getOccurrence( this.getOntologyManager().getValueTopicType() );
		if (occ != null) {
			return occ.getData();
		}
		else {
			return "";
		}
	}


	protected void initValue(String value) throws Exception {
		if ((value != null) && (value.length() > 0)) {
			this.getWrappedTopic().createOccurrence( null, null, this.getOntologyManager().getValueTopicType(), value, EMPTY_SCOPE );
		}
	}

	
	public void setValue(User setter, String value) throws OntologyManagerException, DynamicRightsManagerException {
		DynamicRightsManager drm = this.getOntologyManager().getDynamicRightsManager();
		if (drm != null) {
			drm.checkChangeAttributeValue( setter, this );
		}
		
		if (value == null) {
			value ="";
		}
		
		try {
			String oldValue;
			org.tm4j.topicmap.Occurrence occ = this.getOccurrence( this.getOntologyManager().getValueTopicType() );
			if (occ != null) {
				oldValue = occ.getData();
				if (value.equals(oldValue)) return;
				occ.setData( value );
			}
			else {
				if (value.length() == 0) return;
				oldValue = "";
				this.initValue( value );
			}

			this.incVersion();
			this.getOntologyManager().fireAttributeValueChanged( this, setter, oldValue );
		}
		catch (Exception e) {
			throw new OntologyManagerException( "Error setting attribute value: " + e );
		}
	}


	public Topic getType() {
		OntologyManagerImpl omi = this.getOntologyManager();
		Collection c = this.getWrappedTopic().getTypes();
		if (c != null) {
			Iterator it = c.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) {
						return (Topic)obj;
					}
				}
			}
		}
		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: setter beachten
		int len = (type != null) ? 2 : 1;
		org.tm4j.topicmap.Topic[] types = new org.tm4j.topicmap.Topic[len];
		types[0] = this.getOntologyManager().getAttributeTopicType();
		if (type != null) {
			types[1] = ((TopicImpl)type).getWrappedTopic();
		}
		
		try {
			this.getWrappedTopic().setTypes( types );
			this.incVersion();
		}
		catch (Exception e) {
			throw new OntologyManagerException( e );
		}
	}


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


	public Attributeable getAttributeable() {
		return this.getOntologyManager().getAttributeable( this.getWrappedTopic() );
	}


	public Rating addRating(User rater, double value) throws RatingManagerException,DynamicRightsManagerException {
		Rating r = this.getRating( rater );
		if (r != null) {
			r.setValue( value );
		}
		else {
			RatingManager rm = this.getOntologyManager().getRatingManager();
			if (rm != null) {
				r = rm.createRating( rater, value );
				rm.addRating( this, r );
			}
		}
		return r;
	}


	public Collection getRatings() {
		if (this.getOntologyManager().getRatingManager() != null) {
			return this.getOntologyManager().getRatingManager().getRatings( this );
		}
		else {
			return Collections.EMPTY_SET;
		}
	}


	public double getAverageRatingValue() {
		if (this.getOntologyManager().getRatingManager() != null) {
			return this.getOntologyManager().getRatingManager().getAverageRatingValue( this );
		}
		else {
			return Rating.NEUTRAL;
		}
	}


	public int getRatingsCount() {
		if (this.getOntologyManager().getRatingManager() != null) {
			return this.getOntologyManager().getRatingManager().getRatingsCount( this );
		}
		else {
			return 0;
		}
	}


	public Rating getRating(User user) {
		if (this.getOntologyManager().getRatingManager() != null) {
			return this.getOntologyManager().getRatingManager().getRating( this, user );
		}
		else {
			return null;
		}
	}


	public String toString() {
		String s = this.getName();
		return "Attribute " + (s.length() > 0 ? ("\"" + s + "\""): "(unnamed)") + ", id=" + this.getId() + ", value=" + this.getValue();
	}

}
