/*******************************************************************************
 * Copyright (c) 2005, 2010 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
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.codegen;

import java.text.MessageFormat;

import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;

public class StackMapFrame {
	public static final int USED = 1;
	public static final int SAME_FRAME = 0;
	public static final int CHOP_FRAME = 1;
	public static final int APPEND_FRAME = 2;
	public static final int SAME_FRAME_EXTENDED = 3;
	public static final int FULL_FRAME = 4;
	public static final int SAME_LOCALS_1_STACK_ITEMS = 5;
	public static final int SAME_LOCALS_1_STACK_ITEMS_EXTENDED = 6;

	public int pc;
	public int numberOfStackItems;
	private int numberOfLocals;
	public int localIndex;
	public VerificationTypeInfo[] locals;
	public VerificationTypeInfo[] stackItems;
	private int numberOfDifferentLocals = -1;
	public int tagBits;

public StackMapFrame(int initialLocalSize) {
	this.locals = new VerificationTypeInfo[initialLocalSize];
	this.numberOfLocals = -1;
	this.numberOfDifferentLocals = -1;
}
public int getFrameType(StackMapFrame prevFrame) {
	final int offsetDelta = getOffsetDelta(prevFrame);
	switch(this.numberOfStackItems) {
		case 0 :
			switch(numberOfDifferentLocals(prevFrame)) {
				case 0 :
					return offsetDelta <= 63 ? SAME_FRAME : SAME_FRAME_EXTENDED;
				case 1 :
				case 2 :
				case 3 :
					return APPEND_FRAME;
				case -1 :
				case -2 :
				case -3 :
					return CHOP_FRAME;
			}
			break;
		case 1 :
			switch(numberOfDifferentLocals(prevFrame)) {
				case 0 :
					return offsetDelta <= 63 ? SAME_LOCALS_1_STACK_ITEMS : SAME_LOCALS_1_STACK_ITEMS_EXTENDED;
			}
	}
	return FULL_FRAME;
}
public void addLocal(int resolvedPosition, VerificationTypeInfo info) {
	if (this.locals == null) {
		this.locals = new VerificationTypeInfo[resolvedPosition + 1];
		this.locals[resolvedPosition] = info;
	} else {
		final int length = this.locals.length;
		if (resolvedPosition >= length) {
			System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length);
		}
		this.locals[resolvedPosition] = info;
	}
}
public void addStackItem(VerificationTypeInfo info) {
	if (info == null) {
		throw new IllegalArgumentException("info cannot be null"); //$NON-NLS-1$
	}
	if (this.stackItems == null) {
		this.stackItems = new VerificationTypeInfo[1];
		this.stackItems[0] = info;
		this.numberOfStackItems = 1;
	} else {
		final int length = this.stackItems.length;
		if (this.numberOfStackItems == length) {
			System.arraycopy(this.stackItems, 0, this.stackItems = new VerificationTypeInfo[length + 1], 0, length);
		}
		this.stackItems[this.numberOfStackItems++] = info;
	}
}
public void addStackItem(TypeBinding binding) {
	if (this.stackItems == null) {
		this.stackItems = new VerificationTypeInfo[1];
		this.stackItems[0] = new VerificationTypeInfo(binding);
		this.numberOfStackItems = 1;
	} else {
		final int length = this.stackItems.length;
		if (this.numberOfStackItems == length) {
			System.arraycopy(this.stackItems, 0, this.stackItems = new VerificationTypeInfo[length + 1], 0, length);
		}
		this.stackItems[this.numberOfStackItems++] = new VerificationTypeInfo(binding);
	}
}
public StackMapFrame duplicate() {
	int length = this.locals.length;
	StackMapFrame result = new StackMapFrame(length);
	result.numberOfLocals = -1;
	result.numberOfDifferentLocals = -1;
	result.pc = this.pc;
	result.numberOfStackItems = this.numberOfStackItems;

	if (length != 0) {
		result.locals = new VerificationTypeInfo[length];
		for (int i = 0; i < length; i++) {
			final VerificationTypeInfo verificationTypeInfo = this.locals[i];
			if (verificationTypeInfo != null) {
				result.locals[i] = verificationTypeInfo.duplicate();
			}
		}
	}
	length = this.numberOfStackItems;
	if (length != 0) {
		result.stackItems = new VerificationTypeInfo[length];
		for (int i = 0; i < length; i++) {
			result.stackItems[i] = this.stackItems[i].duplicate();
		}
	}
	return result;
}
public int numberOfDifferentLocals(StackMapFrame prevFrame) {
	if (this.numberOfDifferentLocals != -1) return this.numberOfDifferentLocals;
	if (prevFrame == null) {
		this.numberOfDifferentLocals = 0;
		return 0;
	}
	VerificationTypeInfo[] prevLocals = prevFrame.locals;
	VerificationTypeInfo[] currentLocals = this.locals;
	int prevLocalsLength = prevLocals == null ? 0 : prevLocals.length;
	int currentLocalsLength = currentLocals == null ? 0 : currentLocals.length;
	int prevNumberOfLocals = prevFrame.getNumberOfLocals();
	int currentNumberOfLocals = getNumberOfLocals();

	int result = 0;
	if (prevNumberOfLocals == 0) {
		if (currentNumberOfLocals != 0) {
			// need to check if there is a hole in the locals
			result = currentNumberOfLocals; // append if no hole and currentNumberOfLocals <= 3
			int counter = 0;
			for(int i = 0; i < currentLocalsLength && counter < currentNumberOfLocals; i++) {
				if (currentLocals[i] != null) {
					switch(currentLocals[i].id()) {
						case TypeIds.T_double :
						case TypeIds.T_long :
							i++;
					}
					counter++;
				} else {
					result = Integer.MAX_VALUE;
					this.numberOfDifferentLocals = result;
					return result;
				}
			}
		}
	} else if (currentNumberOfLocals == 0) {
		// need to check if there is a hole in the prev locals
		int counter = 0;
		result = -prevNumberOfLocals; // chop frame if no hole and prevNumberOfLocals <= 3
		for(int i = 0; i < prevLocalsLength && counter < prevNumberOfLocals; i++) {
			if (prevLocals[i] != null) {
				switch(prevLocals[i].id()) {
					case TypeIds.T_double :
					case TypeIds.T_long :
						i++;
				}
				counter++;
			} else {
				result = Integer.MAX_VALUE;
				this.numberOfDifferentLocals = result;
				return result;
			}
		}
	} else {
		// need to see if prevLocals matches with currentLocals
		int indexInPrevLocals = 0;
		int indexInCurrentLocals = 0;
		int currentLocalsCounter = 0;
		int prevLocalsCounter = 0;
		currentLocalsLoop: for (;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) {
			VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals];
			if (currentLocal != null) {
				currentLocalsCounter++;
				switch(currentLocal.id()) {
					case TypeIds.T_double :
					case TypeIds.T_long :
						indexInCurrentLocals++; // next entry  is null
				}
			}
			if (indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals) {
				VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals];
				if (prevLocal != null) {
					prevLocalsCounter++;
					switch(prevLocal.id()) {
						case TypeIds.T_double :
						case TypeIds.T_long :
							indexInPrevLocals++; // next entry  is null
					}
				}
				// now we need to check if prevLocal matches with currentLocal
				// the index must be the same
				if (equals(prevLocal, currentLocal) && indexInPrevLocals == indexInCurrentLocals) {
					if (result != 0) {
						result = Integer.MAX_VALUE;
						this.numberOfDifferentLocals = result;
						return result;
					}
				} else {
					// locals at the same location are not equals - this has to be a full frame
					result = Integer.MAX_VALUE;
					this.numberOfDifferentLocals = result;
					return result;
				}
				indexInPrevLocals++;
				continue currentLocalsLoop;
			}
			// process remaining current locals
			if (currentLocal != null) {
				result++;
			} else {
				result = Integer.MAX_VALUE;
				this.numberOfDifferentLocals = result;
				return result;
			}
			indexInCurrentLocals++;
			break currentLocalsLoop;
		}
		if (currentLocalsCounter < currentNumberOfLocals) {
			for(;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) {
				VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals];
				if (currentLocal == null) {
					result = Integer.MAX_VALUE;
					this.numberOfDifferentLocals = result;
					return result;
				}
				result++;
				currentLocalsCounter++;
				switch(currentLocal.id()) {
					case TypeIds.T_double :
					case TypeIds.T_long :
						indexInCurrentLocals++; // next entry  is null
				}
			}
		} else if (prevLocalsCounter < prevNumberOfLocals) {
			result = -result;
			// process possible remaining prev locals
			for(; indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals; indexInPrevLocals++) {
				VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals];
				if (prevLocal == null) {
					result = Integer.MAX_VALUE;
					this.numberOfDifferentLocals = result;
					return result;
				}
				result--;
				prevLocalsCounter++;
				switch(prevLocal.id()) {
					case TypeIds.T_double :
					case TypeIds.T_long :
						indexInPrevLocals++; // next entry  is null
				}
			}
		}
	}
	this.numberOfDifferentLocals = result;
	return result;
}
public int getNumberOfLocals() {
	if (this.numberOfLocals != -1) {
		return this.numberOfLocals;
	}
	int result = 0;
	final int length = this.locals == null ? 0 : this.locals.length;
	for(int i = 0; i < length; i++) {
		if (this.locals[i] != null) {
			switch(this.locals[i].id()) {
				case TypeIds.T_double :
				case TypeIds.T_long :
					i++;
			}
			result++;
		}
	}
	this.numberOfLocals = result;
	return result;
}
public int getOffsetDelta(StackMapFrame prevFrame) {
	if (prevFrame == null) return this.pc;
	return prevFrame.pc == -1 ? this.pc : this.pc - prevFrame.pc - 1;
}
@Override
public String toString() {
	StringBuffer buffer = new StringBuffer();
	printFrame(buffer, this);
	return String.valueOf(buffer);
}
private void printFrame(StringBuffer buffer, StackMapFrame frame) {
	String pattern = "[pc : {0} locals: {1} stack items: {2}\nlocals: {3}\nstack: {4}\n]"; //$NON-NLS-1$
	int localsLength = frame.locals == null ? 0 : frame.locals.length;
	buffer.append(MessageFormat.format(
		pattern,
		new Object[] {
			Integer.toString(frame.pc),
			Integer.toString(frame.getNumberOfLocals()),
			Integer.toString(frame.numberOfStackItems),
			print(frame.locals, localsLength),
			print(frame.stackItems, frame.numberOfStackItems)
		}
	));
}
private String print(VerificationTypeInfo[] infos, int length) {
	StringBuffer buffer = new StringBuffer();
	buffer.append('[');
	if (infos != null) {
		for (int i = 0; i < length; i++) {
			if (i != 0) buffer.append(',');
			VerificationTypeInfo verificationTypeInfo = infos[i];
			if (verificationTypeInfo == null) {
				buffer.append("top"); //$NON-NLS-1$
				continue;
			}
			buffer.append(verificationTypeInfo);
		}
	}
	buffer.append(']');
	return String.valueOf(buffer);
}
public void putLocal(int resolvedPosition, VerificationTypeInfo info) {
	if (this.locals == null) {
		this.locals = new VerificationTypeInfo[resolvedPosition + 1];
		this.locals[resolvedPosition] = info;
	} else {
		final int length = this.locals.length;
		if (resolvedPosition >= length) {
			System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length);
		}
		this.locals[resolvedPosition] = info;
	}
}
public void replaceWithElementType() {
	VerificationTypeInfo info = this.stackItems[this.numberOfStackItems - 1];
	VerificationTypeInfo info2 = info.duplicate();
	info2.replaceWithElementType();
	this.stackItems[this.numberOfStackItems - 1] = info2;
}
public int getIndexOfDifferentLocals(int differentLocalsCount) {
	for (int i = this.locals.length - 1; i >= 0; i--) {
		VerificationTypeInfo currentLocal = this.locals[i];
		if (currentLocal == null) {
			// check the previous slot
			continue;
		} else {
			differentLocalsCount--;
		}
		if (differentLocalsCount == 0) {
			return i;
		}
	}
	return 0;
}
private boolean equals(VerificationTypeInfo info, VerificationTypeInfo info2) {
	if (info == null) {
		return info2 == null;
	}
	if (info2 == null) return false;
	return info.equals(info2);
}
}
