/*******************************************************************************
 * Copyright (c) 2016, 2017 GK Software AG.
 * 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:
 *     Stephan Herrmann - initial API and implementation
 *******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.compiler.lookup;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import org.aspectj.org.eclipse.jdt.internal.compiler.util.Messages;

/**
 * Used for superimposing external annotations (served by an {@link ITypeAnnotationWalker})
 * over signatures of a {@link SourceTypeBinding}.
 */
class ExternalAnnotationSuperimposer extends TypeBindingVisitor {

	public static void apply(SourceTypeBinding typeBinding, String externalAnnotationPath) {
		ZipFile zipFile = null;
		try {
			File annotationBase = new File(externalAnnotationPath);
			if (annotationBase.exists()) {
				String binaryTypeName = String.valueOf(typeBinding.constantPoolName());
				String relativeFileName = binaryTypeName.replace('.', '/')+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;

				InputStream input;
				if (annotationBase.isDirectory()) {
					input = new FileInputStream(externalAnnotationPath+'/'+relativeFileName);
				} else {
					zipFile = new ZipFile(externalAnnotationPath);
					ZipEntry zipEntry = zipFile.getEntry(relativeFileName);
					if (zipEntry == null)
						return;
					input = zipFile.getInputStream(zipEntry);
				}
				annotateType(typeBinding, new ExternalAnnotationProvider(input, binaryTypeName), typeBinding.environment);
			}
		} catch (FileNotFoundException e) {
			// file not found is expected
		} catch (IOException e) {
			typeBinding.scope.problemReporter().abortDueToInternalError(Messages.bind(Messages.abort_externaAnnotationFile, 
						new String[] {String.valueOf(typeBinding.readableName()), externalAnnotationPath, e.getMessage()}));
		} finally {
			if (zipFile != null)
				try {
					zipFile.close();
				} catch (IOException e) {
					// nothing
				}
		}
	}

	static void annotateType(SourceTypeBinding binding, ExternalAnnotationProvider provider, LookupEnvironment environment) {
		ITypeAnnotationWalker typeWalker = provider.forTypeHeader(environment);
		if (typeWalker != null && typeWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
			ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
			TypeVariableBinding[] typeParameters = binding.typeVariables();
			for (int i = 0; i < typeParameters.length; i++) {
				if (visitor.go(typeWalker.toTypeParameter(true, i)))
					typeParameters[i] = visitor.superimpose(typeParameters[i], TypeVariableBinding.class);
			}
		}
		binding.externalAnnotationProvider = provider; // for superimposing method signatures
	}

	public static void annotateFieldBinding(FieldBinding field, ExternalAnnotationProvider provider, LookupEnvironment environment) {
		char[] fieldSignature = field.genericSignature();
		if (fieldSignature == null && field.type != null)
			fieldSignature = field.type.signature();
		ITypeAnnotationWalker walker = provider.forField(field.name, fieldSignature, environment);
		ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
		if (visitor.go(walker))
			field.type = visitor.superimpose(field.type, TypeBinding.class);
	}

	public static void annotateMethodBinding(MethodBinding method, ExternalAnnotationProvider provider, LookupEnvironment environment) {
		char[] methodSignature = method.genericSignature();
		if (methodSignature == null)
			methodSignature = method.signature();
		ITypeAnnotationWalker walker = provider.forMethod(method.selector, methodSignature, environment);
		if (walker != null && walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
			ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
			TypeVariableBinding[] typeParams = method.typeVariables;
			for (short i = 0; i < typeParams.length; i++) {
				if (visitor.go(walker.toTypeParameter(false, i)))
					typeParams[i] = visitor.superimpose(typeParams[i], TypeVariableBinding.class);
			}
			if (!method.isConstructor()) {
				if (visitor.go(walker.toMethodReturn()))
					method.returnType = visitor.superimpose(method.returnType, TypeBinding.class);
			}
			TypeBinding[] parameters = method.parameters;
			for (short i = 0; i < parameters.length; i++) {
				if (visitor.go(walker.toMethodParameter(i)))
					parameters[i] = visitor.superimpose(parameters[i], TypeBinding.class);
			}
		}
	}

	private ITypeAnnotationWalker currentWalker;
	private TypeBinding typeReplacement;
	private LookupEnvironment environment;
	private boolean isReplacing;
	
	ExternalAnnotationSuperimposer(LookupEnvironment environment) {
		this.environment = environment;
	}

	/** for constructing a memento of the superimposer's current state. */
	private ExternalAnnotationSuperimposer(TypeBinding typeReplacement, boolean isReplacing, ITypeAnnotationWalker walker) {
		this.typeReplacement = typeReplacement;
		this.isReplacing = isReplacing;
		this.currentWalker = walker;
	}
	private ExternalAnnotationSuperimposer snapshot() {
		ExternalAnnotationSuperimposer memento = new ExternalAnnotationSuperimposer(this.typeReplacement, this.isReplacing, this.currentWalker);
		// soft reset:
		this.typeReplacement = null;
		this.isReplacing = false;
		return memento;
	}
	private void restore(ExternalAnnotationSuperimposer memento) {
		this.isReplacing = memento.isReplacing;
		this.currentWalker = memento.currentWalker;
	}

	boolean go(ITypeAnnotationWalker walker) {
		// hard reset:
		reset();
		this.typeReplacement = null;
		this.isReplacing = false;
		// and start anew:
		this.currentWalker = walker;
		return walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
	}

	<T extends TypeBinding> T superimpose(T type, Class<? extends T> cl) {
		TypeBindingVisitor.visit(this, type);
		if (cl.isInstance(this.typeReplacement))
			return cl.cast(this.typeReplacement);
		return type;
	}
	
	private TypeBinding goAndSuperimpose(ITypeAnnotationWalker walker, TypeBinding type) {
		// no reset here
		if (walker == ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER)
			return type;
		this.currentWalker = walker;
		
		TypeBindingVisitor.visit(this, type);

		if (this.typeReplacement == null)
			return type;
		this.isReplacing = true;
		TypeBinding answer = this.typeReplacement;
		this.typeReplacement = null;
		return answer;
	}
	
	@Override
	public boolean visit(ArrayBinding arrayBinding) {
		ExternalAnnotationSuperimposer memento = snapshot();
		try {
			int dims = arrayBinding.dimensions;
			AnnotationBinding[][] annotsOnDims = new AnnotationBinding[dims][];
			ITypeAnnotationWalker walker = this.currentWalker;
			for (int i = 0; i < dims; i++) {
				IBinaryAnnotation[] binaryAnnotations = walker.getAnnotationsAtCursor(arrayBinding.id, false);
				if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
					annotsOnDims[i] = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
					this.isReplacing = true;
				} else {
					annotsOnDims[i] = Binding.NO_ANNOTATIONS;
				}
				walker = walker.toNextArrayDimension();
			}
			TypeBinding leafComponentType = goAndSuperimpose(walker, arrayBinding.leafComponentType());
			if (this.isReplacing) {
				this.typeReplacement = this.environment.createArrayType(leafComponentType, dims, AnnotatableTypeSystem.flattenedAnnotations(annotsOnDims));
			}
		} finally {
			restore(memento);
		}
		return false;
	}
	@Override
	public boolean visit(BaseTypeBinding baseTypeBinding) {
		return false; // no null annotations
	}
	@Override
	public boolean visit(IntersectionTypeBinding18 intersectionTypeBinding18) {
		return false; // shouldn't occur in declarations
	}
	@Override
	public boolean visit(ParameterizedTypeBinding parameterizedTypeBinding) {
		ExternalAnnotationSuperimposer memento = snapshot();
		try {
			IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(parameterizedTypeBinding.id, false);
			AnnotationBinding[] annotations = Binding.NO_ANNOTATIONS;
			if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
				annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
				this.isReplacing = true;
			}

			TypeBinding[] typeArguments = parameterizedTypeBinding.typeArguments();
			TypeBinding[] newArguments = new TypeBinding[typeArguments.length];
			for (int i = 0; i < typeArguments.length; i++) {
				newArguments[i] = goAndSuperimpose(memento.currentWalker.toTypeArgument(i), typeArguments[i]);
			}
			if (this.isReplacing)
				this.typeReplacement = this.environment.createParameterizedType(parameterizedTypeBinding.genericType(), newArguments, parameterizedTypeBinding.enclosingType(), annotations);
			return false;
		} finally {
			restore(memento);
		}		
	}
	@Override
	public boolean visit(RawTypeBinding rawTypeBinding) {
		return visit((ReferenceBinding)rawTypeBinding);
	}
	@Override
	public boolean visit(ReferenceBinding referenceBinding) {
		IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(referenceBinding.id, false);
		if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS)
			this.typeReplacement = this.environment.createAnnotatedType(referenceBinding, BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null));
		return false;
	}
	@Override
	public boolean visit(TypeVariableBinding typeVariable) {
		return visit((ReferenceBinding) typeVariable);
	}
	@Override
	public boolean visit(WildcardBinding wildcardBinding) {
		TypeBinding bound = wildcardBinding.bound;
		ExternalAnnotationSuperimposer memento = snapshot();
		try {
			if (bound != null) {
				bound = goAndSuperimpose(memento.currentWalker.toWildcardBound(), bound);
			}
			IBinaryAnnotation[] binaryAnnotations = memento.currentWalker.getAnnotationsAtCursor(-1, false); 
			if (this.isReplacing || binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
				TypeBinding[] otherBounds = wildcardBinding.otherBounds;
				if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
					AnnotationBinding[] annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
					this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind, annotations);
				} else {
					this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind);
				}
			}
		} finally {
			restore(memento);
		}
		return false;
	}
}
