
/**
 * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *         Florian Pirchner - Initial implementation
 */



package org.eclipse.osbp.dsl.entity.xtext.ui.type;

import java.io.IOException;

import org.eclipse.core.resources.IResource;
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.ResourceSet;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.access.IMirror;
import org.eclipse.xtext.common.types.access.TypeResource;
import org.eclipse.xtext.common.types.access.impl.IndexedJvmTypeAccess;
import org.eclipse.xtext.common.types.access.impl.IndexedJvmTypeAccess.ShadowedTypeException;
import org.eclipse.xtext.common.types.access.impl.URIHelperConstants;
import org.eclipse.xtext.common.types.access.jdt.JdtTypeMirror;
import org.eclipse.xtext.common.types.access.jdt.JdtTypeProvider;
import org.eclipse.xtext.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EntityJdtTypeProvider extends JdtTypeProvider {

	private static final String PRIMITIVES = URIHelperConstants.PRIMITIVES_URI
			.segment(0);
	private static final Logger LOGGER = LoggerFactory
			.getLogger(EntityJdtTypeProvider.class);

	public EntityJdtTypeProvider(IJavaProject javaProject,
			ResourceSet resourceSet, IndexedJvmTypeAccess indexedJvmTypeAccess,
			WorkingCopyOwner workingCopyOwner) {
		super(javaProject, resourceSet, indexedJvmTypeAccess, workingCopyOwner);
	}

	public EntityJdtTypeProvider(IJavaProject javaProject,
			ResourceSet resourceSet, IndexedJvmTypeAccess indexedJvmTypeAccess) {
		super(javaProject, resourceSet, indexedJvmTypeAccess);
	}

	public EntityJdtTypeProvider(IJavaProject javaProject,
			ResourceSet resourceSet) {
		super(javaProject, resourceSet);
	}

	@Override
	public JvmType findTypeByName(String name) {
		String signature = getSignature(name);
		if (signature == null)
			return null;
		URI resourceURI = getTypeUriHelper().createResourceURI(signature);
		if (resourceURI.segment(0) == PRIMITIVES) {
			return findPrimitiveType(signature, resourceURI);
		} else {
			return findObjectType(signature, resourceURI);
		}
	}

	/* @Nullable */
	private String getSignature(String name) {
		if (Strings.isEmpty(name))
			throw new IllegalArgumentException("null");
		String signature = null;
		try {
			signature = name.startsWith("[") ? name : Signature
					.createTypeSignature(name, true);
		} catch (IllegalArgumentException e) {
			return null;
		}
		return signature;
	}

	private JvmType findPrimitiveType(/* @NonNull */String signature, /* @NonNull */
			URI resourceURI) {
		TypeResource resource = (TypeResource) getResourceForJavaURI(
				resourceURI, true);
		JvmType result = findTypeBySignature(signature, resource);
		return result;
	}

	/* @Nullable */
	private JvmType findObjectType(/* @NonNull */String signature, /* @NonNull */
			URI resourceURI) {
		TypeResource resource = getLoadedResourceForJavaURI(resourceURI);
		try {
			JvmType result = findLoadedOrDerivedObjectType(signature,
					resourceURI, resource);
			if (result != null || resource != null) {
				if (result != null && !canLink(result.getQualifiedName())) {
					return null;
				}
				return result;
			}
			try {
				return findObjectTypeInJavaProject(signature, resourceURI);
			} catch (JavaModelException e) {
				return null;
			} catch (NullPointerException e) { // JDT throws NPEs see
												// https://bugs.eclipse.org/bugs/show_bug.cgi?id=369391
				return null;
			}
		} catch (ShadowedTypeException e) {
			return null;
		}
	}

	/* @Nullable */
	private TypeResource getLoadedResourceForJavaURI(
	/* @NonNull */URI resourceURI) {
		TypeResource resource = (TypeResource) getResourceForJavaURI(
				resourceURI, false);
		return resource;
	}

	/* @Nullable */
	private JvmType findLoadedOrDerivedObjectType(/* @NonNull */String signature, /*
																				 * @
																				 * NonNull
																				 */
			URI resourceURI,
			/* @Nullable */TypeResource resource) {
		JvmType result = resource != null ? findTypeBySignature(signature,
				resource) : null;
		if (result != null) {
			return result;
		}
		result = findObjectTypeInIndex(signature, resourceURI);
		if (result != null) {
			return result;
		}
		return null;
	}

	/* @Nullable */
	private JvmType findObjectTypeInJavaProject(/* @NonNull */String signature, /*
																				 * @
																				 * NonNull
																				 */
			URI resourceURI) throws JavaModelException {
		IType type = findObjectTypeInJavaProject(resourceURI);
		if (type != null) {
			try {
				return createResourceAndFindType(resourceURI, type, signature);
			} catch (IOException ioe) {
				return null;
			} catch (WrappedException wrapped) {
				if (wrapped.getCause() instanceof IOException) {
					return null;
				}
				throw wrapped;
			}
		}
		return null;
	}

	private IType findObjectTypeInJavaProject(/* @NonNull */URI resourceURI)
			throws JavaModelException {
		String topLevelType = resourceURI
				.segment(resourceURI.segmentCount() - 1);
		int lastDot = topLevelType.lastIndexOf('.');
		String packageName = null;
		String typeName = topLevelType;
		if (lastDot != -1) {
			typeName = typeName.substring(lastDot + 1);
			packageName = topLevelType.substring(0, lastDot);
		}
		IType type = getJavaProject().findType(packageName, typeName /*
																	 * ,
																	 * workingCopyOwner
																	 */);
		if (type != null && !canLink(type.getFullyQualifiedName())) {
			return null;
		}
		return type;
	}

	private boolean canLink(String typeName) {
		if (typeName == null) {
			return false;
		}
		IndexedJvmTypeAccess indexedJvmTypeAccess = this
				.getIndexedJvmTypeAccess();
		if (indexedJvmTypeAccess != null
				&& indexedJvmTypeAccess.isIndexingPhase(getResourceSet())) {
			// during indexing we don't see project local types.
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=410594
			try {
				IType type = getJavaProject().findType(typeName);
				if (type != null && type.exists()) {
					String enabled = System.getProperty(
							"osbp.linker.constraint", "true");
					if (Boolean.valueOf(enabled)) {
						IResource underlyingResource = type
								.getUnderlyingResource();
						if (underlyingResource == null) {
							return true;
						}
						for (IPackageFragmentRoot root : getJavaProject()
								.getPackageFragmentRoots()) {
							if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
								IResource srcUnderlyingResource = root
										.getUnderlyingResource();
								if (srcUnderlyingResource != null
										&& srcUnderlyingResource
												.contains(underlyingResource)) {
									return false;
								}
							}
						}
					}
					return true;
				}
			} catch (JavaModelException e) {
				LOGGER.error(e.getMessage(), e);
			}
			return false;
		}
		return true;
	}

	/* @Nullable */
	private JvmType createResourceAndFindType(/* @NonNull */URI resourceURI, /*
																			 * @
																			 * NonNull
																			 */
			IType type, /* @NonNull */String signature) throws IOException {
		TypeResource resource = createResource(resourceURI, type);
		resource.load(null);
		return findTypeBySignature(signature, resource);
	}

	private TypeResource createResource(URI resourceURI, IType type) {
		TypeResource resource = new TypeResource(resourceURI);
		resource.setIndexedJvmTypeAccess(getIndexedJvmTypeAccess());
		getResourceSet().getResources().add(resource);
		if (type.exists()) {
			IMirror mirror = createMirror(type);
			resource.setMirror(mirror);
		}
		return resource;
	}

	/* @Nullable */
	private IMirror createMirror(/* @NonNull */IType type) {
		String elementName = type.getElementName();
		if (!elementName.equals(type.getTypeQualifiedName())) {
			// workaround for bug in jdt with binary type names that start with
			// a $ dollar sign
			// e.g. $ImmutableList
			// it manifests itself in a way that allows to retrieve ITypes but
			// one cannot obtain bindings for that type
			return null;
		}
		return new JdtTypeMirror(type, getJdtBasedTypeFactory());
	}

	private JvmType findObjectTypeInIndex(/* @NonNull */String signature, /*
																		 * @NonNull
																		 */
			URI resourceURI) {
		IndexedJvmTypeAccess indexedJvmTypeAccess = getIndexedJvmTypeAccess();
		if (indexedJvmTypeAccess != null) {
			URI proxyURI = resourceURI.appendFragment(getTypeUriHelper()
					.getFragment(signature));
			EObject candidate = indexedJvmTypeAccess.getIndexedJvmType(
					proxyURI, getResourceSet(), true);
			if (candidate instanceof JvmType) {
				return (JvmType) candidate;
			}
		}
		return null;
	}
}
