package org.eclipse.emf.refactor.smells.uml24;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.refactor.smells.interfaces.IModelSmellFinder;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Property;


public final class EqualAttributesinSiblingClasses implements IModelSmellFinder {

	@Override
	public LinkedList<LinkedList<EObject>> findSmell(EObject root) {
		LinkedList<LinkedList<EObject>> results = new LinkedList<LinkedList<EObject>>();
		List<Property> attributes = getAllClassAttributes(root);
		for (Property attribute : attributes) {
			Class owningClass = attribute.getClass_();
			List<Class> superClasses = owningClass.getSuperClasses();
			for (Class superClass : superClasses) {
				if (eachSubClassContainsAttribute(superClass, attribute)) {
					LinkedList<EObject> result = new LinkedList<EObject>();
					result.add(attribute.getClass_());
					result.add(attribute);
					results.add(result);
				}
			}
		}
		return results;
	}

	private boolean eachSubClassContainsAttribute(Class superClass, Property attribute) {
		List<Class> subClasses = new ArrayList<Class>();
		List<Class> allClasses = getAllClasses(superClass.getModel());
		for (Class modelClass : allClasses) {
			if (modelClass != attribute.getClass_() && modelClass.getSuperClasses().contains(superClass)) {
				subClasses.add(modelClass);
			}
		}
		if (subClasses.isEmpty()) return false;
		for (Class subClass : subClasses) {
			if (! classContainsEqualAttribute(subClass, attribute)) {
				return false;
			}
		}
		return true;
	}
	
	private boolean classContainsEqualAttribute(Class cls, Property attribute) {
		if (attribute.getClass_().equals(cls)) return true;
		boolean classHasEqualAttribute = false;
		for (Property attr : cls.getOwnedAttributes()) {
			if (! haveSameNames(attr, attribute)) continue;
			if (! haveSameType(attr, attribute)) continue;
			if (! haveSameVisibilities(attr, attribute)) continue;
			if (! haveSameMultiplicities(attr, attribute)) continue;
			if (! haveSameAggregations(attr, attribute)) continue;
			if (! haveSameDefaultValues(attr, attribute)) continue;
			if (! haveSameDerivedProperties(attr, attribute)) continue;
			if (! haveSameLeafProperties(attr, attribute)) continue;
			if (! haveSameReadOnlyProperties(attr, attribute)) continue;
			if (! haveSameUniqueProperties(attr, attribute)) continue;
			if (! haveSameOrderedProperties(attr, attribute)) continue;
			if (! haveSameStaticProperties(attr, attribute)) continue;
			if (! haveSameDerivedUnionProperties(attr, attribute)) continue;
			if ((attr.getAssociation() != null) && (attribute.getAssociation() != null)) {
				if (getOtherSideUpper(attr) != getOtherSideUpper(attribute)) continue;
			}
			classHasEqualAttribute = true;
			break;
		}
		return classHasEqualAttribute;
	}
	
	private int getOtherSideUpper(Property attribute) {
		int upper = 0;
		for (Property ae : attribute.getAssociation().getMemberEnds()) {
			if (! ae.equals(attribute)) upper = ae.getUpper();
		}
		return upper;
	}

	private boolean haveSameDerivedUnionProperties(Property att1, Property att2) {
		return (att1.isDerivedUnion() == att2.isDerivedUnion());
	}
	
	private boolean haveSameStaticProperties(Property att1, Property att2) {
		return (att1.isStatic() == att2.isStatic());
	}

	private boolean haveSameOrderedProperties(Property att1, Property att2) {
		return (att1.isOrdered() == att2.isOrdered());
	}
	
	private boolean haveSameUniqueProperties(Property att1, Property att2) {
		return (att1.isUnique() == att2.isUnique());
	}
	
	private boolean haveSameReadOnlyProperties(Property att1, Property att2) {
		return (att1.isReadOnly() == att2.isReadOnly());
	}
	
	private boolean haveSameLeafProperties(Property att1, Property att2) {
		return (att1.isLeaf() == att2.isLeaf());
	}
	
	private boolean haveSameDerivedProperties(Property att1, Property att2) {
		return (att1.isDerived() == att2.isDerived());
	}

	private boolean haveSameDefaultValues(Property att1, Property att2) {
		if ((att1.getDefault() == null) && (att2.getDefault() == null)) return true;
		if ((att1.getDefault() != null) 
				&& (att2.getDefault() != null)
				&& (att1.getDefault().equals(att2.getDefault()))) return true;
		return false;
	}

	private boolean haveSameAggregations(Property att1, Property att2) {
		return att1.getAggregation().equals(att2.getAggregation());
	}

	private boolean haveSameMultiplicities(Property att1, Property att2) {
		return ((att1.getLower() == att2.getLower()) 
				&& (att1.getUpper() == att2.getUpper()));
	}

	private boolean haveSameVisibilities(Property att1, Property att2) {
		return att1.getVisibility().equals(att2.getVisibility());
	}

	private boolean haveSameNames(Property att1, Property att2) {
		return att1.getName().equals(att2.getName());
	}

	private boolean haveSameType(Property att1, Property att2) {
		if ((att1.getType() == null) && (att2.getType() == null)) return true;
		if ((att1.getType() != null) 
				&& (att2.getType() != null)
				&& (att1.getType().equals(att2.getType()))) return true;
		return false;
	}

	private ArrayList<Class> getAllClasses(Model model) {
		ArrayList<Class> classes = new ArrayList<Class>();
//		TreeIterator<EObject> iter = model.eResource().getAllContents();
		TreeIterator<EObject> iter = getRoot(model).eAllContents();
		while (iter.hasNext()) {
			EObject eObject = iter.next();
			if (eObject instanceof Class) {
				classes.add((Class) eObject);
			}			
		}		
		return classes;
	}
	
	private EObject getRoot(EObject eObject) {
		if (eObject.eContainer() == null) return eObject;
		else return getRoot(eObject.eContainer());
	}

	private List<Property> getAllClassAttributes(EObject root) {
		List<Property> attributes = new ArrayList<Property>();
		TreeIterator<EObject> iter = root.eAllContents();
		while (iter.hasNext()) {
			EObject eObject = iter.next();
			if (eObject instanceof Property) {
				Property prop = (Property) eObject;
				if (prop.getClass_() != null) {
					attributes.add(prop);
				}
			}
		}
		return attributes;
	}	
}