package br.uem.din.architectureEvolution.helpers;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Collection;

import org.junit.BeforeClass;
import org.junit.Test;

import br.uem.din.architectureEvolution.helpers.ModelElementHelper;
import br.uem.din.architectureEvolution.helpers.ModelHelper;
import br.uem.din.architectureEvolution.helpers.ModelHelperFactory;

import com.sdmetrics.model.MetaModel;
import com.sdmetrics.model.MetaModelElement;
import com.sdmetrics.model.ModelElement;

public class ModelElementHelperTest {

	private static ModelHelper modelHelper;
	private static final String metaModelURL = "test/br/uem/din/architectureEvolution/resources/metamodel_poseidon4.xml";
	private static MetaModel metaModel;
	
	@BeforeClass
	public static void beforeClass() throws Exception{
		modelHelper = ModelHelperFactory.getModelHelper();
		metaModel = modelHelper.getMetaModel(metaModelURL);
	}

	@Test
	public void isInterface_withInterface_returnTrue() {
		ModelElement modelElement = generateModelElementByType("interface");
		boolean result = ModelElementHelper.isInterface(modelElement);
		assertEquals("isInterface should return true for an interface element", true, result);
	}
	
	@Test
	public void isInterface_withClass_returnFalse() {
		ModelElement modelElement = generateModelElementByType("class");
		boolean result = ModelElementHelper.isInterface(modelElement);
		assertEquals("isInterface should return false for a class element", false, result);
	}
	
	@Test
	public void isClass_withClass_returnTrue() {
		ModelElement modelElement = generateModelElementByType("class");
		boolean result = ModelElementHelper.isClass(modelElement);
		assertEquals("isClass should return true for a class element", true, result);
	}
	
	@Test
	public void isClass_withComponent_returnFalse() {
		ModelElement modelElement = generateModelElementByType("component");
		boolean result = ModelElementHelper.isClass(modelElement);
		assertEquals("isClass should return false for a component element", false, result);
	}
	
	@Test
	public void isComponent_withComponent_returnTrue() {
		ModelElement modelElement = generateModelElementByType("component");
		boolean result = ModelElementHelper.isComponent(modelElement);
		assertEquals("isComponent should return true for a component element", true, result);
	}
	
	@Test
	public void isComponent_withInterface_returnFalse() {
		ModelElement modelElement = generateModelElementByType("interface");
		boolean result = ModelElementHelper.isComponent(modelElement);
		assertEquals("isComponent should return false for an interface element", false, result);
	}
	
	@Test
	public void getStereotypes_elementWithoutStereotypes_returnEmptyCollection() {
		ModelElement modelElement = generateModelElementByType("component");
		Collection<ModelElement> result = ModelElementHelper.getStereotypes(modelElement);
		assertEquals("getStereotypes should return an empty collection", 0, result.size());
	}
	
	@Test
	public void getStereotypes_elementWithStereotypes_returnAll() {
		Collection<ModelElement> stereotypes = new ArrayList<ModelElement>();
		stereotypes.add(generateModelElementByType("stereotype"));
		stereotypes.add(generateModelElementByType("stereotype"));
		
		ModelElement modelElement = generateModelElementByType("component");
		modelElement.setSetAttribute("stereotypes", stereotypes);
		
		Collection<ModelElement> result = ModelElementHelper.getStereotypes(modelElement);
		
		assertEquals("getStereotypes should return a collection with 2 stereotypes", 2, result.size());
	}
	
	@Test
	public void getOwnedElementsOfType_elementWithoutOwnedElements_returnEmptyCollection() {
		ModelElement modelElement = generateModelElementByType("component");
		Collection<ModelElement> result = ModelElementHelper.getOwnedElementsOfType(modelElement, "class");
		assertEquals("getOwnedElementsOfType should return an empty collection", 0, result.size());
	}
	
	@Test
	public void getOwnedElementsOfType_elementWithOwnedElements_returnAllOfType() {
		ModelElement modelElement = generateModelElementByType("component");
		modelElement.addRelation(MetaModelElement.CONTEXT, generateModelElementByType("class"));
		modelElement.addRelation(MetaModelElement.CONTEXT, generateModelElementByType("class"));
		
		Collection<ModelElement> result = ModelElementHelper.getOwnedElementsOfType(modelElement, "class");
		assertEquals("getOwnedElementsOfType should return a collection with 2 classes", 2, result.size());
	}
	
	private ModelElement generateModelElementByType(String typeName) {
		ModelElement modelElement = new ModelElement(metaModel.getType(typeName));
		return modelElement;
	}
}
