package br.uem.din.metrics.concernDrivenMetrics.interactionBeteweenConcerns;

import java.util.HashSet;
import java.util.Set;

import br.uem.din.architectureEvolution.representation.Component;
import br.uem.din.architectureEvolution.representation.Concern;
import br.uem.din.architectureEvolution.representation.Element;
import br.uem.din.architectureEvolution.representation.Interface;
import br.uem.din.architectureEvolution.representation.Operation;

public class CIBCResult {

	private final Concern concern;
	private final Set<Concern> interlacedConcerns = new HashSet<Concern>();

	public CIBCResult(Concern concern, Element context, Component component){
		this.concern = concern;
		addInterlacedConcerns(context, component);
	}

	public void addInterlacedConcerns(Element context, Component component) {
		if (context instanceof Component)
			inspectComponent(component);
		else if (context instanceof Interface){
			inspectImplementedInterfaces(component);
			inspectRequiredInterfaces(component);
		}
		else
			inspectOperations(component);
		
		interlacedConcerns.remove(concern);
	}

	private void inspectComponent(Component component) {
		getInterlacedConcerns().addAll(component.getConcerns());
		inspectImplementedInterfaces(component);
		inspectRequiredInterfaces(component);
	}

	private void inspectImplementedInterfaces(Component component) {
		for (Interface i : component.getImplementedInterfaces()) {
			getInterlacedConcerns().addAll(i.getConcerns());
			inspectOperations(i);
		}
	}

	private void inspectRequiredInterfaces(Component component) {
		for (Interface i : component.getRequiredInterfaces()) {
			getInterlacedConcerns().addAll(i.getConcerns());
			inspectOperations(i);
		}
	}
	
	private void inspectOperations(Interface i) {
		for (Operation operation : i.getOperations()) {
			getInterlacedConcerns().addAll(operation.getConcerns());
		}
	}
	
	private void inspectOperations(Component component) {
		for (Interface i : component.getImplementedInterfaces()) {
			inspectOperations(i);
		}
		for (Interface i : component.getRequiredInterfaces()) {
			inspectOperations(i);
		}
	}

	public Concern getConcern() {
		return concern;
	}
	
	public Set<Concern> getInterlacedConcerns() {
		return interlacedConcerns;
	}
	
	@Override
	public String toString() {
		return concern.getName() + ": " + getInterlacedConcerns();
	}
}
