/*******************************************************************************
 * Copyright (c) 2016, 2017 Google, Inc 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:
 *   Stefan Xenos (Google) - Initial implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.nd.java.model;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.classfmt.BinaryTypeFormatter;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.classfmt.ElementValuePairInfo;
import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants;
import org.eclipse.jdt.internal.compiler.env.ClassSignature;
import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
import org.eclipse.jdt.internal.compiler.env.IDependent;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.nd.IReader;
import org.eclipse.jdt.internal.core.nd.db.IString;
import org.eclipse.jdt.internal.core.nd.java.JavaNames;
import org.eclipse.jdt.internal.core.nd.java.NdAnnotation;
import org.eclipse.jdt.internal.core.nd.java.NdAnnotationValuePair;
import org.eclipse.jdt.internal.core.nd.java.NdConstant;
import org.eclipse.jdt.internal.core.nd.java.NdConstantAnnotation;
import org.eclipse.jdt.internal.core.nd.java.NdConstantArray;
import org.eclipse.jdt.internal.core.nd.java.NdConstantClass;
import org.eclipse.jdt.internal.core.nd.java.NdConstantEnum;
import org.eclipse.jdt.internal.core.nd.java.NdMethod;
import org.eclipse.jdt.internal.core.nd.java.NdMethodException;
import org.eclipse.jdt.internal.core.nd.java.NdMethodParameter;
import org.eclipse.jdt.internal.core.nd.java.NdResourceFile;
import org.eclipse.jdt.internal.core.nd.java.NdType;
import org.eclipse.jdt.internal.core.nd.java.NdTypeAnnotation;
import org.eclipse.jdt.internal.core.nd.java.NdTypeId;
import org.eclipse.jdt.internal.core.nd.java.NdTypeInterface;
import org.eclipse.jdt.internal.core.nd.java.NdTypeParameter;
import org.eclipse.jdt.internal.core.nd.java.NdTypeSignature;
import org.eclipse.jdt.internal.core.nd.java.NdVariable;
import org.eclipse.jdt.internal.core.nd.java.TypeRef;
import org.eclipse.jdt.internal.core.util.CharArrayBuffer;

/**
 * Implementation of {@link IBinaryType} that reads all its content from the index
 */
public class IndexBinaryType implements IBinaryType {
	private final TypeRef typeRef;

	private boolean simpleAttributesInitialized;
	private char[] enclosingMethod;
	private char[] enclosingType;
	private char[] fileName;
	private char[] superclassName;
	private int modifiers;
	private boolean isAnonymous;
	private boolean isLocal;
	private boolean isMember;

	private long tagBits;

	private char[] binaryTypeName;

	private static final IBinaryAnnotation[] NO_ANNOTATIONS = new IBinaryAnnotation[0];
	private static final int[] NO_PATH = new int[0];

	public IndexBinaryType(TypeRef type, char[] indexPath) {
		this.typeRef = type;
		this.fileName = indexPath;
	}

	public boolean exists() {
		return this.typeRef.get() != null;
	}

	@Override
	public int getModifiers() {
		initSimpleAttributes();

		return this.modifiers;
	}

	@Override
	public boolean isBinaryType() {
		return true;
	}

	@Override
	public char[] getFileName() {
		return this.fileName;
	}

	@Override
	public IBinaryAnnotation[] getAnnotations() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				return toAnnotationArray(this.typeRef.get().getAnnotations());
			} else {
				return NO_ANNOTATIONS;
			}
		}
	}

	private static IBinaryAnnotation[] toAnnotationArray(List<? extends NdAnnotation> annotations) {
		if (annotations.isEmpty()) {
			return NO_ANNOTATIONS;
		}
		IBinaryAnnotation[] result = new IBinaryAnnotation[annotations.size()];

		for (int idx = 0; idx < result.length; idx++) {
			result[idx] = createBinaryAnnotation(annotations.get(idx));
		}
		return result;
	}

	@Override
	public IBinaryTypeAnnotation[] getTypeAnnotations() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				return createBinaryTypeAnnotations(type.getTypeAnnotations());
			}
		}
		return null;
	}

	@Override
	public char[] getEnclosingMethod() {
		initSimpleAttributes();

		return this.enclosingMethod;
	}

	@Override
	public char[] getEnclosingTypeName() {
		initSimpleAttributes();

		return this.enclosingType;
	}

	@Override
	public IBinaryField[] getFields() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				List<NdVariable> variables = type.getVariables();

				if (variables.isEmpty()) {
					return null;
				}

				IBinaryField[] result = new IBinaryField[variables.size()];
				for (int fieldIdx = 0; fieldIdx < variables.size(); fieldIdx++) {
					result[fieldIdx] = createBinaryField(variables.get(fieldIdx));
				}
				return result;
			} else {
				return null;
			}
		}
	}

	@Override
	public char[] getGenericSignature() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				if (!type.getFlag(NdType.FLG_GENERIC_SIGNATURE_PRESENT)) {
					return null;
				}
				CharArrayBuffer buffer = new CharArrayBuffer();
				NdTypeParameter.getSignature(buffer, type.getTypeParameters());
				NdTypeSignature superclass = type.getSuperclass();
				if (superclass != null) {
					superclass.getSignature(buffer);
				}
				for (NdTypeInterface nextInterface : type.getInterfaces()) {
					nextInterface.getInterface().getSignature(buffer);
				}
				return buffer.getContents();
			} else {
				return null;
			}
		}
	}

	@Override
	public char[][] getInterfaceNames() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				List<NdTypeInterface> interfaces = type.getInterfaces();

				if (interfaces.isEmpty()) {
					return null;
				}

				char[][] result = new char[interfaces.size()][];
				for (int idx = 0; idx < interfaces.size(); idx++) {
					NdTypeSignature nextInterface = interfaces.get(idx).getInterface();

					result[idx] = nextInterface.getRawType().getBinaryName();
				}
				return result;
			} else {
				return null;
			}
		}
	}

	@Override
	public IBinaryNestedType[] getMemberTypes() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				List<NdType> declaredTypes = type.getTypeId().getDeclaredTypes();
				if (declaredTypes.isEmpty()) {
					return null;
				}

				NdResourceFile resFile = type.getResourceFile();
				IString javaRoot = resFile.getPackageFragmentRoot();

				// Filter out all the declared types which are at different java roots (only keep the ones belonging
				// to the same .jar file or to another .class file in the same folder).
				List<IBinaryNestedType> result = new ArrayList<>();
				for (NdType next : declaredTypes) {
					NdResourceFile nextResFile = next.getResourceFile();

					if (nextResFile.getPackageFragmentRoot().compare(javaRoot, true) == 0) {
						result.add(createBinaryNestedType(next));
					}
				}
				return result.isEmpty() ? null : result.toArray(new IBinaryNestedType[result.size()]);
			} else {
				return null;
			}
		}
	}

	private IBinaryNestedType createBinaryNestedType(NdType next) {
		return new IndexBinaryNestedType(next.getTypeId().getBinaryName(), next.getDeclaringType().getBinaryName(),
				next.getModifiers());
	}

	@Override
	public IBinaryMethod[] getMethods() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				List<NdMethod> methods = type.getMethodsInDeclarationOrder();

				if (methods.isEmpty()) {
					return null;
				}

				IBinaryMethod[] result = new IBinaryMethod[methods.size()];
				for (int idx = 0; idx < result.length; idx++) {
					result[idx] = createBinaryMethod(methods.get(idx));
				}

				return result;
			} else {
				return null;
			}
		}
	}

	@Override
	public char[][][] getMissingTypeNames() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				IString string = type.getMissingTypeNames();
				if (string.length() == 0) {
					return null;
				}
				char[] missingTypeNames = string.getChars();
				char[][] paths = CharOperation.splitOn(',', missingTypeNames);
				char[][][] result = new char[paths.length][][];
				for (int idx = 0; idx < paths.length; idx++) {
					result[idx] = CharOperation.splitOn('/', paths[idx]);
				}
				return result;
			} else {
				return null;
			}
		}
	}

	@Override
	public char[] getName() {
		initSimpleAttributes();

		return this.binaryTypeName;
	}

	@Override
	public char[] getSourceName() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				return type.getSourceName();
			} else {
				return new char[0];
			}
		}
	}

	@Override
	public char[] getSuperclassName() {
		initSimpleAttributes();

		return this.superclassName;
	}

	@Override
	public long getTagBits() {
		initSimpleAttributes();

		return this.tagBits;
	}

	@Override
	public boolean isAnonymous() {
		initSimpleAttributes();

		return this.isAnonymous;
	}

	@Override
	public boolean isLocal() {
		initSimpleAttributes();

		return this.isLocal;
	}

	@Override
	public boolean isMember() {
		initSimpleAttributes();

		return this.isMember;
	}

	@Override
	public char[] sourceFileName() {
		try (IReader rl = this.typeRef.lock()) {
			NdType type = this.typeRef.get();
			if (type != null) {
				char[] result = type.getSourceFileName().getChars();
				if (result.length == 0) {
					return null;
				}
				return result;
			} else {
				return null;
			}
		}
	}

	@Override
	public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker, Object member,
			LookupEnvironment environment) {
		return walker;
	}

	private IBinaryMethod createBinaryMethod(NdMethod ndMethod) {
		return IndexBinaryMethod.create().setAnnotations(toAnnotationArray(ndMethod.getAnnotations()))
				.setModifiers(ndMethod.getModifiers()).setIsConstructor(ndMethod.isConstructor())
				.setArgumentNames(getArgumentNames(ndMethod)).setDefaultValue(unpackValue(ndMethod.getDefaultValue()))
				.setExceptionTypeNames(getExceptionTypeNames(ndMethod))
				.setGenericSignature(getGenericSignatureFor(ndMethod))
				.setMethodDescriptor(ndMethod.getMethodDescriptor())
				.setParameterAnnotations(getParameterAnnotations(ndMethod))
				.setSelector(ndMethod.getSelector()).setTagBits(ndMethod.getTagBits())
				.setIsClInit(ndMethod.isClInit()).setTypeAnnotations(createBinaryTypeAnnotations(ndMethod.getTypeAnnotations()));
	}

	private static IBinaryTypeAnnotation[] createBinaryTypeAnnotations(List<? extends NdTypeAnnotation> typeAnnotations) {
		if (typeAnnotations.isEmpty()) {
			return null;
		}
		IBinaryTypeAnnotation[] result = new IBinaryTypeAnnotation[typeAnnotations.size()];
		int idx = 0;
		for (NdTypeAnnotation next : typeAnnotations) {
			IBinaryAnnotation annotation = createBinaryAnnotation(next);
			int[] typePath = getTypePath(next.getTypePath());
			int info = 0;
			int info2 = 0;
			switch (next.getTargetType()) {
				case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER:
				case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER:
					info = next.getTargetInfoArg0();
					break;
				case AnnotationTargetTypeConstants.CLASS_EXTENDS:
					info = next.getTarget();
					break;
				case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND:
				case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND:
					info = next.getTargetInfoArg0();
					info2 = next.getTargetInfoArg1();
					break;
				case AnnotationTargetTypeConstants.FIELD:
				case AnnotationTargetTypeConstants.METHOD_RETURN:
				case AnnotationTargetTypeConstants.METHOD_RECEIVER:
					break;
				case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER :
					info = next.getTarget();
					break;
				case AnnotationTargetTypeConstants.THROWS :
					info = next.getTarget();
					break;

				default:
					throw new IllegalStateException("Target type not handled " + next.getTargetType()); //$NON-NLS-1$
			}
			result[idx++] = new IndexBinaryTypeAnnotation(next.getTargetType(), info, info2, typePath, annotation);
		}
		return result;
	}

	private static int[] getTypePath(byte[] typePath) {
		if (typePath.length == 0) {
			return NO_PATH;
		}
		int[] result = new int[typePath.length];
		for (int idx = 0; idx < typePath.length; idx++) {
			result[idx] = typePath[idx];
		}
		return result;
	}

	private static char[] getGenericSignatureFor(NdMethod method) {
		if (!method.hasAllFlags(NdMethod.FLG_GENERIC_SIGNATURE_PRESENT)) {
			return null;
		}
		CharArrayBuffer result = new CharArrayBuffer();
		method.getGenericSignature(result, method.hasAllFlags(NdMethod.FLG_THROWS_SIGNATURE_PRESENT));
		return result.getContents();
	}
	
	private char[][] getArgumentNames(NdMethod ndMethod) {
		// Unlike what its JavaDoc says, IBinaryType returns an empty array if no argument names are available, so
		// we replicate this weird undocumented corner case here.
		char[][] result = ndMethod.getParameterNames();
		int lastNonEmpty = -1;
		for (int idx = 0; idx < result.length; idx++) {
			if (result[idx] != null && result[idx].length != 0) {
				lastNonEmpty = idx;
			}
		}

		if (lastNonEmpty != result.length - 1) {
			char[][] newResult = new char[lastNonEmpty + 1][];
			System.arraycopy(result, 0, newResult, 0, lastNonEmpty + 1);
			return newResult;
		}
		return result;
	}

	private IBinaryAnnotation[][] getParameterAnnotations(NdMethod ndMethod) {
		List<NdMethodParameter> parameters = ndMethod.getMethodParameters();
		if (parameters.isEmpty()) {
			return null;
		}

		IBinaryAnnotation[][] result = new IBinaryAnnotation[parameters.size()][];
		for (int idx = 0; idx < parameters.size(); idx++) {
			NdMethodParameter next = parameters.get(idx);

			result[idx] = toAnnotationArray(next.getAnnotations());
		}

		// int newLength = result.length;
		// while (newLength > 0 && result[newLength - 1] == null) {
		// --newLength;
		// }
		//
		// if (newLength < result.length) {
		// if (newLength == 0) {
		// return null;
		// }
		// IBinaryAnnotation[][] newResult = new IBinaryAnnotation[newLength][];
		// System.arraycopy(result, 0, newResult, 0, newLength);
		// result = newResult;
		// }

		return result;
	}

	private char[][] getExceptionTypeNames(NdMethod ndMethod) {
		List<NdMethodException> exceptions = ndMethod.getExceptions();

		// Although the JavaDoc for IBinaryMethod says that the exception list will be null if empty,
		// the implementation in MethodInfo returns an empty array rather than null. We copy the
		// same behavior here in case something is relying on it. Uncomment the following if the "null"
		// version is deemed correct.

		// if (exceptions.isEmpty()) {
		// return null;
		// }

		char[][] result = new char[exceptions.size()][];
		for (int idx = 0; idx < exceptions.size(); idx++) {
			NdMethodException next = exceptions.get(idx);

			result[idx] = next.getExceptionType().getRawType().getBinaryName();
		}
		return result;
	}

	public static IBinaryField createBinaryField(NdVariable ndVariable) {
		char[] name = ndVariable.getName().getChars();
		Constant constant = null;
		NdConstant ndConstant = ndVariable.getConstant();
		if (ndConstant != null) {
			constant = ndConstant.getConstant();
		}
		if (constant == null) {
			constant = Constant.NotAConstant;
		}

		NdTypeSignature type = ndVariable.getType();

		IBinaryTypeAnnotation[] typeAnnotationArray = createBinaryTypeAnnotations(ndVariable.getTypeAnnotations());

		IBinaryAnnotation[] annotations = toAnnotationArray(ndVariable.getAnnotations());

		CharArrayBuffer signature = new CharArrayBuffer();
		if (ndVariable.hasVariableFlag(NdVariable.FLG_GENERIC_SIGNATURE_PRESENT)) {
			type.getSignature(signature);
		}

		long tagBits = ndVariable.getTagBits();
		return new IndexBinaryField(annotations, constant, signature.getContents(), ndVariable.getModifiers(), name,
				tagBits, typeAnnotationArray, type.getRawType().getFieldDescriptor().getChars());
	}

	public static IBinaryAnnotation createBinaryAnnotation(NdAnnotation ndAnnotation) {
		List<NdAnnotationValuePair> elementValuePairs = ndAnnotation.getElementValuePairs();

		final IBinaryElementValuePair[] resultingPair = new IBinaryElementValuePair[elementValuePairs.size()];

		for (int idx = 0; idx < elementValuePairs.size(); idx++) {
			NdAnnotationValuePair next = elementValuePairs.get(idx);

			resultingPair[idx] = new ElementValuePairInfo(next.getName().getChars(), unpackValue(next.getValue()));
		}

		final char[] binaryName = JavaNames.fieldDescriptorToBinaryName(
				ndAnnotation.getType().getRawType().getFieldDescriptor().getChars());

		return new IBinaryAnnotation() {
			@Override
			public char[] getTypeName() {
				return binaryName;
			}

			@Override
			public IBinaryElementValuePair[] getElementValuePairs() {
				return resultingPair;
			}

			@Override
			public String toString() {
				return BinaryTypeFormatter.annotationToString(this);
			}
		};
	}

	public void initSimpleAttributes() {
		if (!this.simpleAttributesInitialized) {
			this.simpleAttributesInitialized = true;

			try (IReader rl = this.typeRef.lock()) {
				NdType type = this.typeRef.get();
				if (type != null) {
					IString declaringMethod = type.getDeclaringMethod();

					if (declaringMethod.length() != 0) {
						char[] methodName = declaringMethod.getChars();
						this.enclosingMethod = methodName;
						this.enclosingType = type.getDeclaringType().getBinaryName();
					} else {
						NdTypeId typeId = type.getDeclaringType();

						if (typeId != null) {
							this.enclosingType = typeId.getBinaryName();
						}
					}

					this.modifiers = type.getModifiers();
					this.isAnonymous = type.isAnonymous();
					this.isLocal = type.isLocal();
					this.isMember = type.isMember();
					this.tagBits = type.getTagBits();

					NdTypeSignature superclass = type.getSuperclass();
					if (superclass != null) {
						this.superclassName = superclass.getRawType().getBinaryName();
					} else {
						this.superclassName = null;
					}

					this.binaryTypeName = JavaNames.fieldDescriptorToBinaryName(type.getFieldDescriptor().getChars());
				} else {
					this.binaryTypeName = JavaNames.fieldDescriptorToBinaryName(this.typeRef.getFieldDescriptor());
				}
			}
		}
	}

	private static Object unpackValue(NdConstant value) {
		if (value == null) {
			return null;
		}
		if (value instanceof NdConstantAnnotation) {
			NdConstantAnnotation annotation = (NdConstantAnnotation) value;

			return createBinaryAnnotation(annotation.getValue());
		}
		if (value instanceof NdConstantArray) {
			NdConstantArray array = (NdConstantArray) value;

			List<NdConstant> arrayContents = array.getValue();

			Object[] result = new Object[arrayContents.size()];
			for (int idx = 0; idx < arrayContents.size(); idx++) {
				result[idx] = unpackValue(arrayContents.get(idx));
			}
			return result;
		}
		if (value instanceof NdConstantEnum) {
			NdConstantEnum ndConstantEnum = (NdConstantEnum) value;

			NdTypeSignature signature = ndConstantEnum.getType();

			return new EnumConstantSignature(signature.getRawType().getBinaryName(), ndConstantEnum.getValue());
		}
		if (value instanceof NdConstantClass) {
			NdConstantClass constant = (NdConstantClass) value;

			return new ClassSignature(constant.getValue().getRawType().getBinaryName());
		}

		return value.getConstant();
	}

	@Override
	public ExternalAnnotationStatus getExternalAnnotationStatus() {
		return ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
	}
//{ObjectTeams: retrieve class file in workspace:
	// FIXME: sync this with (a) reading EEA, (b) fileName manipulation for JRT
	@Override
	public IBinaryType withClassBytes() throws ClassFormatException, IOException, CoreException {
		File file = new File(String.valueOf(this.fileName));
		if (file.exists())
			return ClassFileReader.read(file);
		int pos = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, this.fileName);
		if (pos != -1) {
			String jarIdentifier = String.valueOf(CharOperation.subarray(this.fileName, 0, pos));
			String fileInJarName = String.valueOf(CharOperation.subarray(this.fileName, pos+1, -1));
			IJavaElement jJar = JavaCore.create(jarIdentifier);
			if (jJar.exists()) {
				ZipFile jarZip = ((JarPackageFragmentRoot) jJar).getJar();
				try {
					return ClassFileReader.read(jarZip, fileInJarName);
				} finally {
					JavaModelManager.getJavaModelManager().closeZipFile(jarZip);
				}
			}
		}
		return this; // could not improve
	}
// SH}

	@Override
	public char[] getModule() {
		// TODO Auto-generated method stub
		return null;
	}
}
