/*******************************************************************************
 * Copyright (c) 2007, 2018 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.pde.api.tools.internal.model;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.launching.AbstractVMInstall;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.api.tools.internal.model.StubArchiveApiTypeContainer.ArchiveApiTypeRoot;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;

/**
 * Class adapter used to create an API type structure
 */
public class TypeStructureBuilder extends ClassVisitor {
	ApiType fType;
	IApiComponent fComponent;
	IApiTypeRoot fFile;

	/**
	 * Builds a type structure for a class file. Note that if an API component
	 * is not specified, then some operations on the resulting {@link IApiType}
	 * will not be available (navigating super types, member types, etc). This
	 * constructor uses ASM7_EXPERIMENTAL
	 *
	 * @param useExperimental
	 * @param cv class file visitor
	 * @param component originating API component or <code>null</code> if
	 *            unknown
	 */
	TypeStructureBuilder(boolean useExperimental, ClassVisitor cv, IApiComponent component, IApiTypeRoot file) {
		super(Opcodes.ASM7_EXPERIMENTAL, cv);
		fComponent = component;
		fFile = file;
	}
	/**
	 * Builds a type structure for a class file. Note that if an API component
	 * is not specified, then some operations on the resulting {@link IApiType}
	 * will not be available (navigating super types, member types, etc).
	 *
	 * @param cv class file visitor
	 * @param component originating API component or <code>null</code> if
	 *            unknown
	 */
	TypeStructureBuilder(ClassVisitor cv, IApiComponent component, IApiTypeRoot file) {
		super(Opcodes.ASM6, cv);
		fComponent = component;
		fFile = file;
	}

	@Override
	public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
		StringBuilder simpleSig = new StringBuilder();
		simpleSig.append('L');
		simpleSig.append(name);
		simpleSig.append(';');
		String enclosingName = null;
		int index = name.lastIndexOf('$');
		if (index > -1) {
			enclosingName = name.substring(0, index).replace('/', '.');
		}
		int laccess = access;
		// TODO: inner types should be have enclosing type as parent instead of
		// component
		if ((laccess & Opcodes.ACC_DEPRECATED) != 0) {
			laccess &= ~Opcodes.ACC_DEPRECATED;
			laccess |= ClassFileConstants.AccDeprecated;
		}
		fType = new ApiType(fComponent, name.replace('/', '.'), simpleSig.toString(), signature, laccess, enclosingName, fFile);
		if (superName != null) {
			fType.setSuperclassName(superName.replace('/', '.'));
		}
		if (interfaces != null && interfaces.length > 0) {
			String[] names = new String[interfaces.length];
			for (int i = 0; i < names.length; i++) {
				names[i] = interfaces[i].replace('/', '.');
			}
			fType.setSuperInterfaceNames(names);
		}
		super.visit(version, laccess, name, signature, superName, interfaces);
	}

	@Override
	public void visitInnerClass(String name, String outerName, String innerName, int access) {
		super.visitInnerClass(name, outerName, innerName, access);
		String currentName = name.replace('/', '.');
		if (currentName.equals(fType.getName())) {
			if (innerName == null) {
				fType.setAnonymous();
			} else if (outerName == null) {
				fType.setLocal();
				fType.setSimpleName(innerName);
			}
		}
		if (outerName != null && innerName != null) {
			// technically speaking innerName != null is not necessary, but this
			// is a workaround for some
			// bogus synthetic types created by another compiler
			String currentOuterName = outerName.replace('/', '.');
			if (currentOuterName.equals(fType.getName())) {
				// this is a real type member defined in the descriptor (not
				// just a reference to a type member)
				fType.addMemberType(currentName, access);
			} else if (currentName.equals(fType.getName())) {
				fType.setModifiers(access);
				fType.setSimpleName(innerName);
				fType.setMemberType();
			}
		}
	}

	@Override
	public void visitOuterClass(String owner, String name, String desc) {
		fType.setEnclosingMethodInfo(name, desc);
	}

	@Override
	public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
		int laccess = access;
		if ((access & Opcodes.ACC_DEPRECATED) != 0) {
			laccess &= ~Opcodes.ACC_DEPRECATED;
			laccess |= ClassFileConstants.AccDeprecated;
		}
		fType.addField(name, desc, signature, laccess, value);
		return null;
	}

	@Override
	public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
		String[] names = null;
		int laccess = access;
		if ((laccess & Opcodes.ACC_DEPRECATED) != 0) {
			laccess &= ~Opcodes.ACC_DEPRECATED;
			laccess |= ClassFileConstants.AccDeprecated;
		}
		if (exceptions != null && exceptions.length > 0) {
			names = new String[exceptions.length];
			for (int i = 0; i < names.length; i++) {
				names[i] = exceptions[i].replace('/', '.');
			}
		}
		final ApiMethod method = fType.addMethod(name, desc, signature, laccess, names);
		return new MethodVisitor(Opcodes.ASM6, super.visitMethod(laccess, name, desc, signature, exceptions)) {
			@Override
			public AnnotationVisitor visitAnnotation(String sig, boolean visible) {
				if (visible && "Ljava/lang/invoke/MethodHandle$PolymorphicSignature;".equals(sig)) { //$NON-NLS-1$
					method.isPolymorphic();
				}
				return super.visitAnnotation(sig, visible);
			}

			@Override
			public AnnotationVisitor visitAnnotationDefault() {
				return new AnnotationDefaultVisitor(method);
			}
		};
	}

	private static IApiType logAndReturn(IApiTypeRoot file, Exception e) {
		if (ApiPlugin.DEBUG_BUILDER) {
			IStatus status = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, NLS.bind(Messages.TypeStructureBuilder_badClassFileEncountered, file.getTypeName()), e);
			ApiPlugin.log(status);
		}
		return null;
	}

	/**
	 * Visit the default value for an annotation
	 */
	static class AnnotationDefaultVisitor extends AnnotationVisitor {
		ApiMethod method;
		Object value;
		StringBuilder buff = new StringBuilder();
		boolean trace = false;
		int traceCount = 0;

		public AnnotationDefaultVisitor(ApiMethod method) {
			super(Opcodes.ASM6);
			this.method = method;
		}

		@Override
		public void visit(String name, Object value) {
			if (trace) {
				appendValue(value);
				traceCount++;
				return;
			}
			this.value = value;
		}

		@Override
		public AnnotationVisitor visitAnnotation(String name, String desc) {
			trace = true;
			return this;
		}

		@Override
		public void visitEnum(String name, String desc, String value) {
			if (trace) {
				appendValue(value);
				traceCount++;
				return;
			}
			this.value = value;
		}

		@Override
		public AnnotationVisitor visitArray(String name) {
			trace = true;
			return this;
		}

		@Override
		public void visitEnd() {
			if (trace) {
				this.value = buff.toString();
				traceCount--;
				trace = traceCount != 0;
			} else {
				method.setDefaultValue(this.value == null ? null : this.value.toString());
			}
		}

		void appendValue(Object val) {
			if (val != null) {
				if (buff.length() < 1) {
					buff.append(val.toString());
				} else {
					buff.append(',').append(val.toString());
				}
			}
		}
	}

	/**
	 * Builds a type structure with the given .class file bytes in the specified
	 * API component.
	 *
	 * @param bytes class file bytes
	 * @param component originating API component
	 * @param file associated class file
	 * @return
	 */
	public static IApiType buildTypeStructure(byte[] bytes, IApiComponent component, IApiTypeRoot file) {
		boolean useExperimental = false;
		try {
			String[] executionEnvironments = component.getExecutionEnvironments();
			if (executionEnvironments.length == 1) {
				String string = executionEnvironments[0];
				IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
				IExecutionEnvironment env = manager.getEnvironment(string);
				IVMInstall[] compatibleVMs = env.getCompatibleVMs();
				Arrays.sort(compatibleVMs, new Comparator<IVMInstall>() {
					@Override
					public int compare(IVMInstall o1, IVMInstall o2) {
						return o1.getName().compareTo(o2.getName());
					}
				});
				for (int i = 0; i < compatibleVMs.length; i++) {
					if (compatibleVMs[i] instanceof AbstractVMInstall) {
						AbstractVMInstall ivmInstall = (AbstractVMInstall) compatibleVMs[i];
						String javaVersion = ivmInstall.getJavaVersion();
						if (i == 0) {
							useExperimental = javaVersion.equals("11"); //$NON-NLS-1$
						}
						boolean strictlyCompatible = env.isStrictlyCompatible(ivmInstall);
						// if strictly compatible, then take that value
						if (strictlyCompatible) {
							useExperimental = javaVersion.equals("11"); //$NON-NLS-1$
							break;
						}
					}
				}
			}

		} catch (Exception e1) {
			// do nothing
		}
		// Till ASM7 is incorporated, use ASM7_EXPERIMENTAL to
		// avoidOperationUnsupportedException if Java 11 is on build path. If
		// not Java
		// 11 then use ASM6
		TypeStructureBuilder visitor = useExperimental ? new TypeStructureBuilder(useExperimental, new ClassNode(), component, file) : new TypeStructureBuilder(new ClassNode(), component, file);
		try {
			ClassReader classReader = new ClassReader(bytes);
			classReader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
		} catch (ArrayIndexOutOfBoundsException e) {
			logAndReturn(file, e);
			return null;
		} catch (IllegalArgumentException iae) {
			// thrown from ASM 5.0 for bad bytecodes
			return logAndReturn(file, iae);
		}
		return visitor.fType;
	}

	/**
	 * Builds a type structure with the given .class file bytes in the specified
	 * API component.
	 *
	 * @param bytes class file bytes
	 * @param component originating API component
	 * @param file associated class file
	 * @return
	 */
	public static void setEnclosingMethod(IApiType enclosingType, ApiType currentAnonymousLocalType) {
		IApiTypeRoot typeRoot = enclosingType.getTypeRoot();
		if (typeRoot instanceof AbstractApiTypeRoot) {
			AbstractApiTypeRoot abstractApiTypeRoot = (AbstractApiTypeRoot) typeRoot;
			EnclosingMethodSetter visitor = new EnclosingMethodSetter(new ClassNode(), currentAnonymousLocalType.getName());
			try {
				ClassReader classReader = new ClassReader(abstractApiTypeRoot.getContents());
				classReader.accept(visitor, ClassReader.SKIP_FRAMES);
			} catch (ArrayIndexOutOfBoundsException e) {
				ApiPlugin.log(e);
			} catch (CoreException e) {
				// bytes could not be retrieved for abstractApiTypeRoot
				ApiPlugin.log(e);
			}
			if (visitor.found) {
				currentAnonymousLocalType.setEnclosingMethodInfo(visitor.name, visitor.signature);
			}
		}
	}

	static class EnclosingMethodSetter extends ClassVisitor {
		String name;
		String signature;
		boolean found = false;
		String typeName;

		public EnclosingMethodSetter(ClassVisitor cv, String typeName) {
			super(Opcodes.ASM6, cv);
			this.typeName = typeName.replace('.', '/');
		}

		@Override
		public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
			if ("<clinit>".equals(name)) { //$NON-NLS-1$
				return null;
			}
			if (!this.found) {
				if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) == 0) {
					this.name = name;
					this.signature = desc;
					if (signature != null) {
						this.signature = signature;
					}
					MethodVisitor mv;
					if ("<init>".equals(name)) { //$NON-NLS-1$
						mv = new TypeNameFinderInConstructor(cv.visitMethod(access, name, desc, signature, exceptions), this);
					} else {
						mv = new TypeNameFinder(cv.visitMethod(access, name, desc, signature, exceptions), this);
					}
					return mv;
				}
			}
			return null;
		}
	}

	static class TypeNameFinder extends MethodVisitor {
		protected EnclosingMethodSetter setter;

		public TypeNameFinder(MethodVisitor mv, EnclosingMethodSetter enclosingMethodSetter) {
			super(Opcodes.ASM6, mv);
			this.setter = enclosingMethodSetter;
		}

		@Override
		public void visitTypeInsn(int opcode, String type) {
			if (setter.typeName.equals(type)) {
				setter.found = true;
			}
		}
	}

	static class TypeNameFinderInConstructor extends TypeNameFinder {
		int lineNumberStart;
		int matchingLineNumber;
		int currentLineNumber = -1;

		public TypeNameFinderInConstructor(MethodVisitor mv, EnclosingMethodSetter enclosingMethodSetter) {
			super(mv, enclosingMethodSetter);
		}

		@Override
		public void visitFieldInsn(int opcode, String owner, String name, String desc) {
			super.visitFieldInsn(opcode, owner, name, desc);
		}

		@Override
		public void visitTypeInsn(int opcode, String type) {
			if (!setter.found && setter.typeName.equals(type)) {
				this.matchingLineNumber = this.currentLineNumber;
				setter.found = true;
			}
		}

		@Override
		public void visitLineNumber(int line, Label start) {
			if (this.currentLineNumber == -1) {
				this.lineNumberStart = line;
			}
			this.currentLineNumber = line;
		}

		@Override
		public void visitEnd() {
			if (setter.found) {
				// check that the line number is between the constructor bounds
				if (this.matchingLineNumber < this.lineNumberStart || this.matchingLineNumber > this.currentLineNumber) {
					setter.found = false;
				}
			}
		}
	}

	@Override
	public String toString() {
		StringBuilder buffer = new StringBuilder();
		buffer.append("Type structure builder for: ").append(fType.getName()); //$NON-NLS-1$
		buffer.append("\nBacked by file: ").append(fFile.getName()); //$NON-NLS-1$
		return buffer.toString();
	}

	public static IApiType buildStubTypeStructure(byte[] contents, IApiComponent apiComponent, ArchiveApiTypeRoot archiveApiTypeRoot) {
		// decode the byte[]
		DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(contents));
		ApiType type = null;
		try {
			Map<Integer, String> pool = new HashMap<>();
			short currentVersion = inputStream.readShort(); // read file version
															// (for now there is
															// only one version)
			short poolSize = inputStream.readShort();
			for (int i = 0; i < poolSize; i++) {
				String readUtf = inputStream.readUTF();
				int index = inputStream.readShort();
				pool.put(Integer.valueOf(index), readUtf);
			}
			int access = 0;
			// access flag was added in version 2 of the stub format
			if (currentVersion >= 2) {
				access = inputStream.readChar();
			}
			int classIndex = inputStream.readShort();
			String name = pool.get(Integer.valueOf(classIndex));
			StringBuilder simpleSig = new StringBuilder();
			simpleSig.append('L');
			simpleSig.append(name);
			simpleSig.append(';');
			type = new ApiType(apiComponent, name.replace('/', '.'), simpleSig.toString(), null, access, null, archiveApiTypeRoot);
			int superclassNameIndex = inputStream.readShort();
			if (superclassNameIndex != -1) {
				String superclassName = pool.get(Integer.valueOf(superclassNameIndex));
				type.setSuperclassName(superclassName.replace('/', '.'));
			}
			int interfacesLength = inputStream.readShort();
			if (interfacesLength != 0) {
				String[] names = new String[interfacesLength];
				for (int i = 0; i < names.length; i++) {
					String interfaceName = pool.get(Integer.valueOf(inputStream.readShort()));
					names[i] = interfaceName.replace('/', '.');
				}
				type.setSuperInterfaceNames(names);
			}
			int fieldsLength = inputStream.readShort();
			for (int i = 0; i < fieldsLength; i++) {
				String fieldName = pool.get(Integer.valueOf(inputStream.readShort()));
				type.addField(fieldName, null, null, 0, null);
			}
			int methodsLength = inputStream.readShort();
			for (int i = 0; i < methodsLength; i++) {
				int isPolymorphic = 0;
				String methodSelector = pool.get(Integer.valueOf(inputStream.readShort()));
				String methodSignature = pool.get(Integer.valueOf(inputStream.readShort()));
				if (currentVersion == 3) {
					isPolymorphic = inputStream.readByte();
				}
				type.addMethod(methodSelector, methodSignature, null, isPolymorphic == 1 ? ApiMethod.Polymorphic : 0, null);
			}
		} catch (IOException e) {
			ApiPlugin.log(e);
		} finally {
			try {
				inputStream.close();
			} catch (IOException e) {
				// ignore
			}
		}
		return type;
	}
}
