/*******************************************************************************
 * Copyright (c) 2016, 2017 GK Software AG.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Stephan Herrmann - initial API and implementation
 *******************************************************************************/
package 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.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import 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;
	}
}
