/*******************************************************************************
 * Copyright (c) 2000, 2004 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.jdt.internal.compiler.ast;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;

public class SwitchStatement extends Statement {

	public Expression expression;
	public Statement[] statements;
	public BlockScope scope;
	public int explicitDeclarations;
	public Label breakLabel;
	public CaseStatement[] cases;
	public CaseStatement defaultCase;
	public int blockStart;
	public int caseCount;
	int[] constants;
	
	// for local variables table attributes
	int preSwitchInitStateIndex = -1;
	int mergedInitStateIndex = -1;

	public FlowInfo analyseCode(
			BlockScope currentScope,
			FlowContext flowContext,
			FlowInfo flowInfo) {

	    try {
			flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo);
			SwitchFlowContext switchContext =
				new SwitchFlowContext(flowContext, this, (breakLabel = new Label()));
	
			// analyse the block by considering specially the case/default statements (need to bind them 
			// to the entry point)
			FlowInfo caseInits = FlowInfo.DEAD_END;
			// in case of statements before the first case
			preSwitchInitStateIndex =
				currentScope.methodScope().recordInitializationStates(flowInfo);
			int caseIndex = 0;
			if (statements != null) {
				boolean didAlreadyComplain = false;
				for (int i = 0, max = statements.length; i < max; i++) {
					Statement statement = statements[i];
					if ((caseIndex < caseCount) && (statement == cases[caseIndex])) { // statement is a case
						this.scope.enclosingCase = cases[caseIndex]; // record entering in a switch case block
						caseIndex++;
						caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
						didAlreadyComplain = false; // reset complaint
					} else if (statement == defaultCase) { // statement is the default case
						this.scope.enclosingCase = defaultCase; // record entering in a switch case block
						caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
						didAlreadyComplain = false; // reset complaint
					}
					if (!statement.complainIfUnreachable(caseInits, scope, didAlreadyComplain)) {
						caseInits = statement.analyseCode(scope, switchContext, caseInits);
					} else {
						didAlreadyComplain = true;
					}
				}
			}
	
			// if no default case, then record it may jump over the block directly to the end
			if (defaultCase == null) {
				// only retain the potential initializations
				flowInfo.addPotentialInitializationsFrom(
					caseInits.mergedWith(switchContext.initsOnBreak));
				mergedInitStateIndex =
					currentScope.methodScope().recordInitializationStates(flowInfo);
				return flowInfo;
			}
	
			// merge all branches inits
			FlowInfo mergedInfo = caseInits.mergedWith(switchContext.initsOnBreak);
			mergedInitStateIndex =
				currentScope.methodScope().recordInitializationStates(mergedInfo);
			return mergedInfo;
	    } finally {
	        if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block
	    }
	}

	/**
	 * Switch code generation
	 *
	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
	 */
	public void generateCode(BlockScope currentScope, CodeStream codeStream) {

	    try {
			if ((bits & IsReachableMASK) == 0) {
				return;
			}
			int pc = codeStream.position;
	
			// prepare the labels and constants
			this.breakLabel.initialize(codeStream);
			CaseLabel[] caseLabels = new CaseLabel[this.caseCount];
			boolean needSwitch = this.caseCount != 0;
			for (int i = 0; i < caseCount; i++) {
				cases[i].targetLabel = (caseLabels[i] = new CaseLabel(codeStream));
			}
			CaseLabel defaultLabel = new CaseLabel(codeStream);
			if (defaultCase != null) {
				defaultCase.targetLabel = defaultLabel;
			}
			// generate expression testes
			expression.generateCode(currentScope, codeStream, needSwitch);
			// generate the appropriate switch table/lookup bytecode
			if (needSwitch) {
				int[] sortedIndexes = new int[this.caseCount];
				// we sort the keys to be able to generate the code for tableswitch or lookupswitch
				for (int i = 0; i < caseCount; i++) {
					sortedIndexes[i] = i;
				}
				int[] localKeysCopy;
				System.arraycopy(this.constants, 0, (localKeysCopy = new int[this.caseCount]), 0, this.caseCount);
				CodeStream.sort(localKeysCopy, 0, this.caseCount - 1, sortedIndexes);

				// for enum constants, actually switch on constant ordinal()
				if (this.expression.resolvedType.isEnum()) {
					codeStream.invokeEnumOrdinal(this.expression.resolvedType.constantPoolName());
				}
				int max = localKeysCopy[this.caseCount - 1];
				int min = localKeysCopy[0];
				if ((long) (caseCount * 2.5) > ((long) max - (long) min)) {
					
					// work-around 1.3 VM bug, if max>0x7FFF0000, must use lookup bytecode
					// see http://dev.eclipse.org/bugs/show_bug.cgi?id=21557
					if (max > 0x7FFF0000 && currentScope.environment().options.complianceLevel < ClassFileConstants.JDK1_4) {
						codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels);
	
					} else {
						codeStream.tableswitch(
							defaultLabel,
							min,
							max,
							this.constants,
							sortedIndexes,
							caseLabels);
					}
				} else {
					codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels);
				}
				codeStream.updateLastRecordedEndPC(this.scope, codeStream.position);
			}
			
			// generate the switch block statements
			int caseIndex = 0;
			if (this.statements != null) {
				for (int i = 0, maxCases = this.statements.length; i < maxCases; i++) {
					Statement statement = this.statements[i];
					if ((caseIndex < this.caseCount) && (statement == this.cases[caseIndex])) { // statements[i] is a case
						this.scope.enclosingCase = this.cases[caseIndex]; // record entering in a switch case block
						if (preSwitchInitStateIndex != -1) {
							codeStream.removeNotDefinitelyAssignedVariables(currentScope, preSwitchInitStateIndex);
						}
						caseIndex++;
					} else {
						if (statement == this.defaultCase) { // statements[i] is a case or a default case
							this.scope.enclosingCase = this.defaultCase; // record entering in a switch case block
							if (preSwitchInitStateIndex != -1) {
								codeStream.removeNotDefinitelyAssignedVariables(currentScope, preSwitchInitStateIndex);
							}
						}
					}
					statement.generateCode(scope, codeStream);
				}
			}
			// place the trailing labels (for break and default case)
			this.breakLabel.place();
			if (defaultCase == null) {
				defaultLabel.place();
			}
			// May loose some local variable initializations : affecting the local variable attributes
			if (mergedInitStateIndex != -1) {
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
				codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
			}
			if (scope != currentScope) {
				codeStream.exitUserScope(this.scope);
			}
			codeStream.recordPositionsFrom(pc, this.sourceStart);
	    } finally {
	        if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block
	    }		
	}

	public StringBuffer printStatement(int indent, StringBuffer output) {

		printIndent(indent, output).append("switch ("); //$NON-NLS-1$
		expression.printExpression(0, output).append(") {"); //$NON-NLS-1$
		if (statements != null) {
			for (int i = 0; i < statements.length; i++) {
				output.append('\n');
				if (statements[i] instanceof CaseStatement) {
					statements[i].printStatement(indent, output);
				} else {
					statements[i].printStatement(indent+2, output);
				}
			}
		}
		output.append("\n"); //$NON-NLS-1$
		return printIndent(indent, output).append('}');
	}

	public void resolve(BlockScope upperScope) {
	
	    try {
			boolean isEnumSwitch = false;
			TypeBinding expressionType = expression.resolveType(upperScope);
			if (expressionType == null)
				return;
			expression.computeConversion(upperScope, expressionType, expressionType);
			checkType: {
				if (expressionType.isBaseType()) {
					if (expression.isConstantValueOfTypeAssignableToType(expressionType, IntBinding))
						break checkType;
					if (expressionType.isCompatibleWith(IntBinding))
						break checkType;
				} else if (expressionType.isEnum()) {
					isEnumSwitch = true;
					break checkType;
				} else if (upperScope.isBoxingCompatibleWith(expressionType, IntBinding)) {
					expression.computeConversion(upperScope, IntBinding, expressionType);
					break checkType;
				}
				upperScope.problemReporter().incorrectSwitchType(expression, expressionType);
				// TODO (philippe) could keep analyzing switch statements in case of error
				return;
			}
			if (statements != null) {
				scope = /*explicitDeclarations == 0 ? upperScope : */new BlockScope(upperScope);
				int length;
				// collection of cases is too big but we will only iterate until caseCount
				cases = new CaseStatement[length = statements.length];
				this.constants = new int[length];
				CaseStatement[] duplicateCaseStatements = null;
				int duplicateCaseStatementsCounter = 0;
				int counter = 0;
				for (int i = 0; i < length; i++) {
					Constant constant;
					final Statement statement = statements[i];
					if ((constant = statement.resolveCase(scope, expressionType, this)) != Constant.NotAConstant) {
						int key = constant.intValue();
						//----check for duplicate case statement------------
						for (int j = 0; j < counter; j++) {
							if (this.constants[j] == key) {
								final CaseStatement currentCaseStatement = (CaseStatement) statement;
								if (duplicateCaseStatements == null) {
									scope.problemReporter().duplicateCase(cases[j]);
									scope.problemReporter().duplicateCase(currentCaseStatement);
									duplicateCaseStatements = new CaseStatement[length];
									duplicateCaseStatements[duplicateCaseStatementsCounter++] = cases[j];
									duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
								} else {
									boolean found = false;
									searchReportedDuplicate: for (int k = 2; k < duplicateCaseStatementsCounter; k++) {
										if (duplicateCaseStatements[k] == statement) {
											found = true;
											break searchReportedDuplicate;
										}
									}
									if (!found) {
										scope.problemReporter().duplicateCase(currentCaseStatement);
										duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
									}
								}
							}
						}
						this.constants[counter++] = key;
					}
				}
				if (length != counter) { // resize constants array
					System.arraycopy(this.constants, 0, this.constants = new int[counter], 0, counter);
				}
			} else {
				if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
					upperScope.problemReporter().undocumentedEmptyBlock(this.blockStart, this.sourceEnd);
				}
			}
			// for enum switch, check if all constants are accounted for (if no default) 
			if (isEnumSwitch && defaultCase == null 
					&& upperScope.environment().options.getSeverity(CompilerOptions.IncompleteEnumSwitch) != ProblemSeverities.Ignore) {
				int constantCount = this.constants == null ? 0 : this.constants.length; // could be null if no case statement
				if (constantCount == caseCount // ignore diagnosis if unresolved constants
						&& caseCount != ((ReferenceBinding)expressionType).enumConstantCount()) {
					FieldBinding[] enumFields = ((ReferenceBinding)expressionType.erasure()).fields();
					for (int i = 0, max = enumFields.length; i <max; i++) {
						FieldBinding enumConstant = enumFields[i];
						if ((enumConstant.modifiers & AccEnum) == 0) continue;
						findConstant : {
							for (int j = 0; j < caseCount; j++) {
								if (enumConstant.id == this.constants[j]) break findConstant;
							}
							// enum constant did not get referenced from switch
							upperScope.problemReporter().missingEnumConstantCase(this, enumConstant);
						}
					}
				}
			}
	    } finally {
	        if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block
	    }
	}

	public void traverse(
			ASTVisitor visitor,
			BlockScope blockScope) {

		if (visitor.visit(this, blockScope)) {
			expression.traverse(visitor, scope);
			if (statements != null) {
				int statementsLength = statements.length;
				for (int i = 0; i < statementsLength; i++)
					statements[i].traverse(visitor, scope);
			}
		}
		visitor.endVisit(this, blockScope);
	}
	
	/**
	 * Dispatch the call on its last statement.
	 */
	public void branchChainTo(Label label) {
		
		// in order to improve debug attributes for stepping (11431)
		// we want to inline the jumps to #breakLabel which already got
		// generated (if any), and have them directly branch to a better
		// location (the argument label).
		// we know at this point that the breakLabel already got placed
		if (this.breakLabel.hasForwardReferences()) {
			label.appendForwardReferencesFrom(this.breakLabel);
		}
	}
}
