/*******************************************************************************
 * Copyright (c) 2000, 2005 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.ui.search;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ContinueStatement;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.WhileStatement;

import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.NodeFinder;

import org.eclipse.jdt.internal.ui.JavaPlugin;

/**
 * Class used to find the target for a break or continue statement according 
 * to the language specification.
 * <p> 
 * The target statement is a while, do, switch, for or a labeled statement.
 * Break is described in section 14.15 of the JLS3 and continue in section 14.16.</p>
 * 
 * @since 3.2
 */
public class BreakContinueTargetFinder extends ASTVisitor {
	private ASTNode fSelected;
	private boolean fIsBreak;
	private SimpleName fLabel;
	private String fContents;//contents are used for scanning to select the right extent of the keyword
	private static final Class[] STOPPERS=        {MethodDeclaration.class, Initializer.class};
	private static final Class[] BREAKTARGETS=    {ForStatement.class, EnhancedForStatement.class, WhileStatement.class, DoStatement.class, SwitchStatement.class};
	private static final Class[] CONTINUETARGETS= {ForStatement.class, EnhancedForStatement.class, WhileStatement.class, DoStatement.class};
	private static final int BRACE_LENGTH= 1;

	/*
	 * Initializes the finder. Returns error message or <code>null</code> if everything is OK.
	 */
	public String initialize(CompilationUnit root, int offset, int length) {
		return initialize(root, NodeFinder.perform(root, offset, length));
	}
	
	/*
	 * Initializes the finder. Returns error message or <code>null</code> if everything is OK.
	 */
	public String initialize(CompilationUnit root, ASTNode node) {
		ASTNode controlNode= getBreakOrContinueNode(node);
		if (controlNode != null){
			fContents= getContents(root);
			if (fContents == null)
				return SearchMessages.BreakContinueTargetFinder_cannot_highlight;

			fSelected= controlNode;
			fIsBreak= fSelected instanceof BreakStatement;
			fLabel= getLabel();
			return null;
		} else {
			return SearchMessages.BreakContinueTargetFinder_no_break_or_continue_selected;
		}
	}

	/* Returns contents or <code>null</code> if there's trouble. */
	private String getContents(CompilationUnit root) {
		try {
			IJavaElement rootElem= root.getJavaElement();
			if ((rootElem instanceof ISourceReference))
				return ((ISourceReference)rootElem).getSource();
			else
				return null;
		} catch (JavaModelException e) {
			//We must handle it here because JavaEditor does not expect an exception
			
			/* showing a dialog here would be too heavy but we cannot just 
             * swallow the exception */
			JavaPlugin.log(e); 
			return null;
		}
	}

	//extract the control node: handle labels
	private ASTNode getBreakOrContinueNode(ASTNode selectedNode) {
		if (selectedNode instanceof BreakStatement)
			return selectedNode;
		if (selectedNode instanceof ContinueStatement)
			return selectedNode;
		if (selectedNode instanceof SimpleName && selectedNode.getParent() instanceof BreakStatement)
			return selectedNode.getParent();
		if (selectedNode instanceof SimpleName && selectedNode.getParent() instanceof ContinueStatement)
			return selectedNode.getParent();
		return null;
	}

	public List perform() {
		return getNodesToHighlight();
	}

	private SimpleName getLabel() {
		if (fIsBreak){
			BreakStatement bs= (BreakStatement) fSelected;
			return bs.getLabel();
		} else {
			ContinueStatement cs= (ContinueStatement) fSelected;
			return cs.getLabel();
		} 
	}
	
	private List getNodesToHighlight() {
		ASTNode targetNode= findTargetNode(fSelected);
		if (!isEnclosingStatement(targetNode))
			return Collections.EMPTY_LIST;
		
		List list= new ArrayList();
		ASTNode node= makeFakeNodeForFirstToken(targetNode);
		if (node != null)
			list.add(node);
		
		if (fIsBreak) {
			node= makeFakeNodeForClosingBrace(targetNode);
			if (node != null)
				list.add(node);
		}
		
		return list;
			
	}

	private boolean isEnclosingStatement(ASTNode targetNode) {
		return (targetNode != null) && !(targetNode instanceof MethodDeclaration) && !(targetNode instanceof Initializer);
	}

	private ASTNode findTargetNode(ASTNode node) {
		do {
			node= node.getParent();
		} while (keepWalkingUp(node));
		return node;
	}

	private ASTNode makeFakeNodeForFirstToken(ASTNode node) {
		try {
			int length= getLengthOfFirstTokenOf(node);
			if (length < 1)
				return node;//fallback
			return makeFakeNode(node.getStartPosition(), length, node.getAST());
		} catch (InvalidInputException e) {
			return node;//fallback
		}
	}

	private SimpleName makeFakeNode(int start, int length, AST ast) {
		String fakeName= makeStringOfLength(length);
		SimpleName name= ast.newSimpleName(fakeName);
		name.setSourceRange(start, length);
		return name;
	}

	private ASTNode makeFakeNodeForClosingBrace(ASTNode targetNode) {
		ASTNode maybeBlock= getOptionalBlock(targetNode);
		if (maybeBlock == null)
			return null;
		
		/* Ideally, we'd scan backwards to find the '}' token, but it may be an overkill
		 * so I'll just assume the closing brace token has a fixed length. */
		return makeFakeNode(ASTNodes.getExclusiveEnd(maybeBlock)-BRACE_LENGTH, BRACE_LENGTH, targetNode.getAST());
	}

	/*
	 * Block cannot be return type here because SwitchStatement has no block 
	 * and yet it does have a closing brace. 
	 */
	private ASTNode getOptionalBlock(ASTNode targetNode) {
		final ASTNode[] maybeBlock= new ASTNode[1];
		targetNode.accept(new ASTVisitor(){
			public boolean visit(ForStatement node) {
				if (node.getBody() instanceof Block)
					maybeBlock[0]= node.getBody(); 
				return false;
			}
			public boolean visit(EnhancedForStatement node) {
				if (node.getBody() instanceof Block)
					maybeBlock[0]= node.getBody(); 
				return false;
			}
			public boolean visit(WhileStatement node) {
				if (node.getBody() instanceof Block)
					maybeBlock[0]= node.getBody(); 
				return false;
			}
			public boolean visit(DoStatement node) {
				if (node.getBody() instanceof Block)
					maybeBlock[0]= node.getBody(); 
				return false;
			}
			public boolean visit(SwitchStatement node) {
				maybeBlock[0]= node; 
				return false;
			}
		});
		return maybeBlock[0];
	}

	private static String makeStringOfLength(int length) {
		char[] chars= new char[length];
		Arrays.fill(chars, 'x');
		return new String(chars);
	}

	//must scan because of unicode
	private int getLengthOfFirstTokenOf(ASTNode node) throws InvalidInputException {
		IScanner scanner= ToolFactory.createScanner(true, true, false, true);
		scanner.setSource(getSource(node).toCharArray());
		scanner.getNextToken();
		return scanner.getRawTokenSource().length;
	}

	private String getSource(ASTNode node) {
		return fContents.substring(node.getStartPosition(), ASTNodes.getInclusiveEnd(node));
	}

	private boolean keepWalkingUp(ASTNode node) {
		if (node == null)
			return false;
		if (isAnyInstanceOf(STOPPERS, node))
			return false;
		if (fLabel != null && LabeledStatement.class.isInstance(node)){
			LabeledStatement ls= (LabeledStatement)node;
			return ! areEqualLabels(ls.getLabel(), fLabel);
		}
		if (fLabel == null &&  fIsBreak && isAnyInstanceOf(BREAKTARGETS, node))
			return false;
		if (fLabel == null && !fIsBreak && isAnyInstanceOf(CONTINUETARGETS, node))
			return false;
		return true;
	}

	//TODO see bug 33739 - resolveBinding always returns null
	//so we just compare names
	private static boolean areEqualLabels(SimpleName labelToMatch, SimpleName labelSelected) {
		return labelSelected.getIdentifier().equals(labelToMatch.getIdentifier());
	}

	private static boolean isAnyInstanceOf(Class[] continueTargets, ASTNode node) {
		for (int i= 0; i < continueTargets.length; i++) {
			if (continueTargets[i].isInstance(node))
				return true;
		}
		return false;
	}
}
