package interactivefeaturelocator.model;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.ntlab.trace.AugmentationInfo;
import org.ntlab.trace.MethodExecution;

public class MethodInfo extends AugmentationInfo {
	private Set<MethodExecution> executions = new HashSet<>();
	private Set<MethodProperty> properties = new HashSet<>();
	private ArrayList<IMethodListener> listeners = new ArrayList<>();
	
	public MethodInfo() {
		// TODO Auto-generated constructor stub
		super();
		for (MethodProperty property : MethodProperty.values()) {
			properties.add(property);
		}
//		properties.addAll(Arrays.asList(MethodProperty.values()));
	}
	
	public void addMethodListener(IMethodListener listener) {
		listeners.add(listener);
	}
	
	public void removeMethodListener(IMethodListener listener) {
		listeners.remove(listener);
	}
	
	public Set<MethodExecution> discardProperty(MethodProperty property) {
		Set<MethodExecution> unreflectedExecutions = (Set<MethodExecution>)((HashSet<MethodExecution>)executions).clone();
		if (properties.contains(property)) {
			properties.remove(property);
			for (IMethodListener listener : listeners) {
				listener.notify(this);
				unreflectedExecutions.removeAll(((DerivationSession)listener).getReflectedMethodExecutions());
				unreflectedExecutions.addAll(((DerivationSession)listener).getUnreflectedMethodExecutions());
			}
		}
		return unreflectedExecutions;
	}
	
	public Set<MethodExecution> discardOtherProperties(MethodProperty property) {
		Set<MethodExecution> unreflectedExecutions = (Set<MethodExecution>)((HashSet<MethodExecution>)executions).clone();
		if (properties.size() == 0 || (properties.contains(property) && properties.size() == 1)) {
			return unreflectedExecutions;
		}
//		for (MethodProperty prop : properties) {
		for (MethodProperty prop : MethodProperty.values()) {
			if (prop != property) {
				properties.remove(prop);
			}
		}
		for (IMethodListener listener : listeners) {
			listener.notify(this);
			unreflectedExecutions.removeAll(((DerivationSession)listener).getReflectedMethodExecutions());
			unreflectedExecutions.addAll(((DerivationSession)listener).getUnreflectedMethodExecutions());
		}
		return unreflectedExecutions;
	}
	
	public Set<MethodProperty> getProperties() {
		return properties;
	}
}
