/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * 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:
 *     IBM Corporation - initial API and implementation
 *     Stephan Herrmann - Contribution for
 *							Bug 423504 - [1.8] Implement "18.5.3 Functional Interface Parameterization Inference"
 *							Bug 426676 - [1.8][compiler] Wrong generic method type inferred from lambda expression
 *							Bug 426542 - [1.8] Most specific method not picked when one method has intersection type as type parameter
 *							Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation.
 *     Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
 *                          Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
 *     Jesper S Møller - Contributions for bug 381345 : [1.8] Take care of the Java 8 major version
 *                          Bug 527554 - [18.3] Compiler support for JEP 286 Local-Variable Type
 *******************************************************************************/

package org.eclipse.jdt.internal.compiler.lookup;

import java.util.Set;

import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;

/**
 * Abstraction used for intersection casts in Java 8 + and inferred types:
 * <ul>
 * <li>type inference at 1.8+</li>
 * <li>lub at 1.8+</li>
 * <li>projections for 'var' at 10+</li>
 * </ul>
 */
public class IntersectionTypeBinding18 extends ReferenceBinding {

	public ReferenceBinding [] intersectingTypes;
	private ReferenceBinding javaLangObject;
	int length;
	
	public IntersectionTypeBinding18(ReferenceBinding[] intersectingTypes, LookupEnvironment environment) {
		this.intersectingTypes = intersectingTypes;
		this.length = intersectingTypes.length;
		if (!intersectingTypes[0].isClass()) {
			this.javaLangObject = environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null);
			this.modifiers |= ClassFileConstants.AccInterface;
		}
	}
	
	private IntersectionTypeBinding18(IntersectionTypeBinding18 prototype) {
		this.intersectingTypes = prototype.intersectingTypes;
		this.length = prototype.length;
		if (!this.intersectingTypes[0].isClass()) {
			this.javaLangObject = prototype.javaLangObject;
			this.modifiers |= ClassFileConstants.AccInterface;
		}
	}
	
	@Override
	public TypeBinding clone(TypeBinding enclosingType) {
		return new IntersectionTypeBinding18(this);
	}

	@Override
	protected MethodBinding[] getInterfaceAbstractContracts(Scope scope, boolean replaceWildcards, boolean filterDefaultMethods) throws InvalidInputException {
		int typesLength = this.intersectingTypes.length;
		MethodBinding[][] methods = new MethodBinding[typesLength][];
		int contractsLength = 0;
		for (int i = 0; i < typesLength; i++) {
			methods[i] = this.intersectingTypes[i].getInterfaceAbstractContracts(scope, replaceWildcards, true);
			contractsLength += methods[i].length;
		}
		MethodBinding[] contracts = new MethodBinding[contractsLength];
		int idx = 0;
		for (int i = 0; i < typesLength; i++) {
			int len = methods[i].length;
			System.arraycopy(methods[i], 0, contracts, idx, len);
			idx += len;
		}
		return contracts;
	}

	@Override
	public boolean hasTypeBit(int bit) { // Stephan ??
		for (int i = 0; i < this.length; i++) {		
			if (this.intersectingTypes[i].hasTypeBit(bit))
				return true;
		}
		return false;
	}

	@Override
	public boolean canBeInstantiated() {
		return false;
	}
	
	@Override
	public boolean canBeSeenBy(PackageBinding invocationPackage) {
		for (int i = 0; i < this.length; i++) {
			if (!this.intersectingTypes[i].canBeSeenBy(invocationPackage))
				return false;
		}
		return true;
	}
	
	@Override
	public boolean canBeSeenBy(Scope scope) {
		for (int i = 0; i < this.length; i++) {
			if (!this.intersectingTypes[i].canBeSeenBy(scope))
				return false;
		}
		return true;
	}
	
	@Override
	public boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding invocationType) {
		for (int i = 0; i < this.length; i++) {
			if (!this.intersectingTypes[i].canBeSeenBy(receiverType, invocationType))
				return false;
		}
		return true;
	}
	
	
	@Override
	public char[] constantPoolName() {
		TypeBinding erasure = erasure();
		if (erasure != this) //$IDENTITY-COMPARISON$
			return erasure.constantPoolName();
		if (this.intersectingTypes[0].id == TypeIds.T_JavaLangObject && this.intersectingTypes.length > 1)
			return this.intersectingTypes[1].constantPoolName(); // improve stack map
		return this.intersectingTypes[0].constantPoolName();
	}

	@Override
	public PackageBinding getPackage() {
		throw new UnsupportedOperationException(); // cannot be referred to
	}
	
	@Override
	public ReferenceBinding[] getIntersectingTypes() {
		return this.intersectingTypes;
	}

	@Override
	public ReferenceBinding superclass() {
		return this.intersectingTypes[0].isClass() ? this.intersectingTypes[0] : this.javaLangObject; 
	}
	
	@Override
	public ReferenceBinding [] superInterfaces() {
		if (this.intersectingTypes[0].isClass()) {
			ReferenceBinding [] superInterfaces = new ReferenceBinding[this.length - 1];
			System.arraycopy(this.intersectingTypes, 1, superInterfaces, 0, this.length - 1);
			return superInterfaces;
		}
		return this.intersectingTypes;
	}
	
	@Override
	public boolean isBoxedPrimitiveType() {
		return this.intersectingTypes[0].isBoxedPrimitiveType();
	}
	
	/* Answer true if the receiver type can be assigned to the argument type (right)
	 */
	@Override
	public boolean isCompatibleWith(TypeBinding right, Scope scope) {

		// easy way out?
		if (TypeBinding.equalsEquals(this, right))
			return true;

		// need to compare two intersection types?
		int rightKind = right.kind();
		TypeBinding[] rightIntersectingTypes = null;
		if (rightKind == INTERSECTION_TYPE && right.boundKind() == Wildcard.EXTENDS) {
			TypeBinding allRightBounds = ((WildcardBinding) right).allBounds();
			if (allRightBounds instanceof IntersectionTypeBinding18)
				rightIntersectingTypes = ((IntersectionTypeBinding18) allRightBounds).intersectingTypes;
		} else if (rightKind == INTERSECTION_TYPE18) {
			rightIntersectingTypes = ((IntersectionTypeBinding18) right).intersectingTypes;
		}
		if (rightIntersectingTypes != null) {
			nextRequired:
			for (TypeBinding required : rightIntersectingTypes) {
				for (TypeBinding provided : this.intersectingTypes) {
					if (provided.isCompatibleWith(required, scope))
						continue nextRequired;
				}
				return false;
			}
			return true;
		}

		// normal case:
		for (int i = 0; i < this.length; i++) {		
			if (this.intersectingTypes[i].isCompatibleWith(right, scope))
				return true;
		}
		return false;
	}
	
	@Override
	public boolean isSubtypeOf(TypeBinding other, boolean simulatingBugJDK8026527) {
		if (TypeBinding.equalsEquals(this, other))
			return true;
		if (other instanceof ReferenceBinding) {
			TypeBinding[] rightIntersectingTypes = ((ReferenceBinding) other).getIntersectingTypes();
			if (rightIntersectingTypes != null && rightIntersectingTypes.length > 1) {
				int numRequired = rightIntersectingTypes.length;
				TypeBinding[] required = new TypeBinding[numRequired];
				System.arraycopy(rightIntersectingTypes, 0, required, 0, numRequired);
				for (int i = 0; i < this.length; i++) {
					TypeBinding provided = this.intersectingTypes[i];
					for (int j = 0; j < required.length; j++) {
						if (required[j] == null) continue;
						if (provided.isSubtypeOf(required[j], simulatingBugJDK8026527)) {
							required[j] = null;
							if (--numRequired == 0)
								return true;
							break;
						}
					}
				}
				return false;
			}
		}
		for (int i = 0; i < this.intersectingTypes.length; i++) {
			if (this.intersectingTypes[i].isSubtypeOf(other, false))
				return true;
		}
		return false;
	}

	@Override
	public TypeBinding erasure() {
		int classIdx = -1;
		for (int i = 0; i < this.intersectingTypes.length; i++) {
			if (this.intersectingTypes[i].isClass() && this.intersectingTypes[i].id != TypeIds.T_JavaLangObject) { // ignore j.l.Object to improve stack map
				if (classIdx == -1) {
					classIdx = i;
				} else {
					classIdx = Integer.MAX_VALUE;
					break;
				}
			}
		}
		if (classIdx > -1 && classIdx < Integer.MAX_VALUE)
			return this.intersectingTypes[classIdx].erasure();
		return this;
	}

	@Override
	public char[] qualifiedSourceName() {
		StringBuffer qualifiedSourceName = new StringBuffer(16);
		for (int i = 0; i < this.length; i++) {		
				qualifiedSourceName.append(this.intersectingTypes[i].qualifiedSourceName());
				if (i != this.length - 1)
					qualifiedSourceName.append(" & "); //$NON-NLS-1$
		}
		return qualifiedSourceName.toString().toCharArray();
	}

	@Override
	public char[] sourceName() {
		StringBuffer srcName = new StringBuffer(16);
		for (int i = 0; i < this.length; i++) {		
				srcName.append(this.intersectingTypes[i].sourceName());
				if (i != this.length - 1)
					srcName.append(" & "); //$NON-NLS-1$
		}
		return srcName.toString().toCharArray();
	}

	@Override
	public char[] readableName() {
		StringBuffer readableName = new StringBuffer(16);
		for (int i = 0; i < this.length; i++) {		
				readableName.append(this.intersectingTypes[i].readableName());
				if (i != this.length - 1)
					readableName.append(" & "); //$NON-NLS-1$
		}
		return readableName.toString().toCharArray();
	}
	@Override
	public char[] shortReadableName() {
		StringBuffer shortReadableName = new StringBuffer(16);
		for (int i = 0; i < this.length; i++) {		
				shortReadableName.append(this.intersectingTypes[i].shortReadableName());
				if (i != this.length - 1)
					shortReadableName.append(" & "); //$NON-NLS-1$
		}
		return shortReadableName.toString().toCharArray();
	}
	@Override
	public boolean isIntersectionType18() {
		return true;
	}
	@Override
	public int kind() {
		return Binding.INTERSECTION_TYPE18;
	}
	@Override
	public String debugName() {
		StringBuffer debugName = new StringBuffer(16);
		for (int i = 0; i < this.length; i++) {		
				debugName.append(this.intersectingTypes[i].debugName());
				if (i != this.length - 1)
					debugName.append(" & "); //$NON-NLS-1$
		}
		return debugName.toString();
	}
	@Override
	public String toString() {
	    return debugName();
	}

	public TypeBinding getSAMType(Scope scope) {
		for (int i = 0, max = this.intersectingTypes.length; i < max; i++) {
			TypeBinding typeBinding = this.intersectingTypes[i];
			MethodBinding methodBinding = typeBinding.getSingleAbstractMethod(scope, true);
			// Why doesn't getSingleAbstractMethod do as the javadoc says, and return null
			// when it is not a SAM type
			if (methodBinding != null && methodBinding.problemId() != ProblemReasons.NoSuchSingleAbstractMethod) {
				return typeBinding; // answer the first SAM we find
			}
		}
		return null;
	}

//{ObjectTeams: enable crossing package boundaries:
	protected
// SH}
	@Override
	void collectInferenceVariables(Set<InferenceVariable> variables) {
		for (int i = 0; i < this.intersectingTypes.length; i++)
			this.intersectingTypes[i].collectInferenceVariables(variables);
	}
	
	@Override
	public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
		ReferenceBinding[] projectedTypes = new ReferenceBinding[this.intersectingTypes.length];
		for (int i = 0; i < this.intersectingTypes.length; ++i) {
			projectedTypes[i] =  this.intersectingTypes[i].upwardsProjection(scope, mentionedTypeVariables);
		}
		return (ReferenceBinding) scope.environment().createIntersectionType18(projectedTypes);
	}

	@Override
	public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
		ReferenceBinding[] projectedTypes = new ReferenceBinding[this.intersectingTypes.length];
		for (int i = 0; i < this.intersectingTypes.length; ++i) {
			projectedTypes[i] = this.intersectingTypes[i].downwardsProjection(scope, mentionedTypeVariables);
		}
		return (ReferenceBinding) scope.environment().createIntersectionType18(projectedTypes);
	}

	@Override
	public boolean mentionsAny(TypeBinding[] parameters, int idx) {
		if (super.mentionsAny(parameters, idx))
			return true;
		for (int i = 0; i < this.intersectingTypes.length; i++) {
			if (this.intersectingTypes[i].mentionsAny(parameters, -1))
				return true;
		}
		return false;
	}
	@Override
	public long updateTagBits() {
		for (TypeBinding intersectingType : this.intersectingTypes)
			this.tagBits |= intersectingType.updateTagBits();
		return super.updateTagBits();
	}
}
