package br.uem.din.architectureEvolution.helpers;
	
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.eclipse.uml2.uml.resources.util.UMLResourcesUtil;

public class XMIHelper {

	public final static ResourceSet RESOURCE_SET;
	 
	static {
		RESOURCE_SET = new ResourceSetImpl();				
	}
	
	public static void init() {
		UMLResourcesUtil.init(RESOURCE_SET);
		registerPathmaps();
		
		RESOURCE_SET.getPackageRegistry()
		.put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
		
		RESOURCE_SET.getResourceFactoryRegistry()
		.getExtensionToFactoryMap()
		.put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
	}
	
	 protected static void registerPathmaps() {
		 String umlResourcePath = UMLResourcesUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();
		 try {
			umlResourcePath = URLDecoder.decode(umlResourcePath, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		URI umlResourcePluginURI = URI.createURI("jar:file:" + umlResourcePath + "!/");
		
		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.LIBRARIES_PATHMAP),
				umlResourcePluginURI.appendSegment("libraries").appendSegment(""));
		
		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.METAMODELS_PATHMAP),
				umlResourcePluginURI.appendSegment("metamodels").appendSegment(""));
		
		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.PROFILES_PATHMAP),
				umlResourcePluginURI.appendSegment("profiles").appendSegment(""));
			
		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.UML_PRIMITIVE_TYPES_LIBRARY_URI),
				umlResourcePluginURI.appendSegment("libraries").appendSegment("UMLPrimitiveTypes.library.uml"));
		
		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.UML_METAMODEL_URI),
				umlResourcePluginURI.appendSegment("metamodels").appendSegment("UML.metamodel.uml"));

		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.UML2_PROFILE_URI),
				umlResourcePluginURI.appendSegment("profiles").appendSegment("UML2.profile.uml"));
		
		RESOURCE_SET.getURIConverter().getURIMap().put(URI.createURI(UMLResource.STANDARD_L2_PROFILE_URI),
				umlResourcePluginURI.appendSegment("profiles").appendSegment("StandardL2.profile.uml"));
		}

	public static void save(org.eclipse.uml2.uml.Package package_, URI uri) throws IOException {
		ArrayList<EObject> contents = new ArrayList<EObject>();
		contents.add(package_);
		save(contents, uri);
	}
	
	public static void save(Collection<EObject> contents, URI uri) throws IOException {
		URI finalUri = uri.appendFileExtension(UMLResource.FILE_EXTENSION);
		Resource resource = RESOURCE_SET.createResource(finalUri);
		resource.getContents().addAll(contents);
		resource.save(null);
	}
	
	protected static org.eclipse.uml2.uml.Generalization createGeneralization(Classifier child, Classifier parent) {
		return child.createGeneralization(parent);
	}
	
	protected static org.eclipse.uml2.uml.Class createClass(org.eclipse.uml2.uml.Package nestingPackage, String name, boolean isAbstract) {
		org.eclipse.uml2.uml.Class createdClass = nestingPackage.createOwnedClass(name, isAbstract);
		return createdClass;
	}
	
	protected static org.eclipse.uml2.uml.Package createPackage(org.eclipse.uml2.uml.Package nestingPackage, String name) {
		org.eclipse.uml2.uml.Package createdPackage = nestingPackage.createNestedPackage(name);
		
		out("Package '" + createdPackage.getQualifiedName() + "' created.");
		
		return createdPackage;
	}
	
	protected static Model createModel(String name) {
		Model model = UMLFactory.eINSTANCE.createModel();
		model.setName(name);
		
		out("Model '" + model.getQualifiedName() + "' created.");
		
		return model;
	}
	
	protected static void out(String output) {
		System.out.println(output);
	}
	
	protected static void err(String error) {
		System.out.println(error);
	}

	public static org.eclipse.uml2.uml.Package load(URI uri) {
        org.eclipse.uml2.uml.Package package_ = null;

        try {
             Resource resource = RESOURCE_SET.getResource(uri, true);

             package_ = (org.eclipse.uml2.uml.Package) EcoreUtil.getObjectByType(
                       resource.getContents(), UMLPackage.Literals.PACKAGE);
        } catch (WrappedException we) {
                err(we.getMessage());
        }

        return package_;
	}
}
