/*******************************************************************************
 * Copyright (c) 2003, 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
 *******************************************************************************/
/*
 * Created on Mar 9, 2004
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package org.eclipse.jst.common.internal.annotations.ui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jdt.ui.text.java.IJavadocCompletionProcessor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jst.common.internal.annotations.core.AnnotationTagParser;
import org.eclipse.jst.common.internal.annotations.core.TagParseEventHandler;
import org.eclipse.jst.common.internal.annotations.core.Token;
import org.eclipse.jst.common.internal.annotations.registry.AnnotationTagRegistry;
import org.eclipse.jst.common.internal.annotations.registry.AttributeValueProposalHelper;
import org.eclipse.jst.common.internal.annotations.registry.AttributeValuesHelper;
import org.eclipse.jst.common.internal.annotations.registry.TagAttribSpec;
import org.eclipse.jst.common.internal.annotations.registry.TagSpec;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.part.FileEditorInput;


/**
 * @author Pat Kelley
 * 
 * To change the template for this generated type comment go to Window - Preferences - Java - Code
 * Generation - Code and Comments
 */
public class AnnotationTagCompletionProc implements IJavadocCompletionProcessor, TagParseEventHandler {
	private static final String[] BOOLEAN_VALID_VALUES = new String[]{"false", "true"}; //$NON-NLS-1$ //$NON-NLS-2$
	ICompilationUnit m_icu;

	IDocument m_doc;

	List m_tags;

	// Instance variables active when maybeCompleteAttribute is live.
	Token m_tagName;

	/**
	 * Set of all attributes names encountered. Only live when maybeCompleteAttribute is live.
	 */
	Set m_attSet = new TreeSet();

	/**
	 * List of Attribute. Only live when maybeCompleAttribute is live.
	 */
	List m_attributes = new ArrayList();

	AnnotationTagParser m_parser = new AnnotationTagParser(this);

	/**
	 * Scope of the tag. TagSpec.TYPE | TagSpec.METHOD | TagSpec.FIELD. Not valid until
	 * getAnnotationArea has been called for a completions request, and only then if
	 * getAnnotationArea() did not return null.
	 */
	int m_tagScope;

	public AnnotationTagCompletionProc() {
		initTagInfo();
	}

	private void initTagInfo() {
		if (m_tags == null)
			m_tags = AnnotationTagRegistry.getAllTagSpecs();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jdt.ui.text.java.IJavadocCompletionProcessor#computeContextInformation(org.eclipse.jdt.core.ICompilationUnit,
	 *      int)
	 */
	public IContextInformation[] computeContextInformation(ICompilationUnit cu, int offset) {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jdt.ui.text.java.IJavadocCompletionProcessor#computeCompletionProposals(org.eclipse.jdt.core.ICompilationUnit,
	 *      int, int, int)
	 */
	public IJavaCompletionProposal[] computeCompletionProposals(ICompilationUnit cu, int offset, int length, int flags) {
		IEditorInput editorInput = new FileEditorInput((IFile) cu.getResource());

		// Set up completion processor state.
		m_doc = JavaUI.getDocumentProvider().getDocument(editorInput);
		m_icu = cu;

		try {
			AnnotationArea area = getAnnotationArea(offset);

			if (area == null) {
				return null;
			}

			// Check for tag completion first. ( the easier case )
			String tsf = getTagSoFarIfNotCompleted(area.beginOffset, offset);

			if (tsf != null) {
				return getTagCompletionsFor(tsf, area, length);
			}

			// Ach, have to try the harder case now, where we parse the
			// annotation
			return maybeCompleteAttribute(area, offset);

		} catch (JavaModelException e) {
			// Silently fail.
			return null;
		} catch (BadLocationException ex) {
			return null;
		}
	}

	private IJavaCompletionProposal[] maybeCompleteAttribute(AnnotationArea area, int cursorPos) throws BadLocationException {
		m_attSet.clear();
		m_attributes.clear();

		m_parser.setParserInput(m_doc.get(area.beginOffset, area.length()));
		m_parser.parse();

		TagSpec ts = null;
		if (m_tagName!=null)
			ts = getTagSpecForTagName(m_tagName.getText());

		// Do we even recognize this tag?
		if (ts == null) {
			return null;
		}

		// Loop through and determine whether the cursor is within a attribute
		// assignment, or between assignements.
		Attribute target = null;
		Attribute last = null;
		Attribute before = null;
		Attribute a = null;
		boolean between = false;
		int rCurPos = area.relativeCursorPos(cursorPos);
		Iterator i = m_attributes.iterator();
		while (i.hasNext()) {
			a = (Attribute) i.next();

			if (a.contains(rCurPos)) {
				target = a;
				break;
			} else if (last != null) {
				// See if the cursor is between, but not directly adjacent to
				// the last two attributes.
				if (rCurPos > last.maxExtent() + 1 && rCurPos < a.minExtent() - 1) {
					between = true;
					break;
				} else if (a.immediatelyPrecedes(rCurPos)) {
					before = a;
					break;
				}
			}
			last = a;
		}

		if (target == null) {
			if (between) {
				// If we're between attributes, suggest all possible attributes.
				return attributeCompletionsFor(ts, cursorPos, 0, "", true); //$NON-NLS-1$
			} else if (before != null) {
				// We're right after the attribute named in 'before', so set the
				// target to it, and fall
				//  through to the target handling code.
				target = before;
			} else {
				// not between and not immediately after an attribute. We are
				// past the end of the parsed annotation.
				//  Only offer suggestions if it looks like the last annotation
				// attribute is valid.
				if (a == null) {
					// No annotations attributes, suggest everything.
					return attributeCompletionsFor(ts, cursorPos, 0, "", true); //$NON-NLS-1$
				} else if (rCurPos > a.maxExtent()) {
					if (a.hasAssignment() && a.hasValue()) {
						// Last annotation was good, and we're past it, so do
						// completions for anything
						return attributeCompletionsFor(ts, cursorPos, 0, "", true); //$NON-NLS-1$
					} else if (a.hasAssignment())
						return attributeValidValuesFor(ts, a, area, cursorPos);
					else
						return attributeCompletionsFor(ts, cursorPos - a.name.length(), 0, a.name.getText(), true);
				} else {
					// Didn't match anything, not past the end - we're probably
					// the first attribute
					// being added to the tag.
					return attributeCompletionsFor(ts, cursorPos, 0, "", true); //$NON-NLS-1$
				}
			}
		}

		// Completion for a partial attribute name?
		if (target.name.immediatelyPrecedes(rCurPos)) {
			return attributeCompletionsFor(ts, area.relativeToAbs(target.name.getBeginning()), target.name.length(), target.name.getText(), !target.hasAssignment());
		}

		// Are we in the middle of a name?
		if (target.name.contains(rCurPos)) {
			// We've opted to replace the entire name for this case, which seems
			// to make the most sense.
			return attributeCompletionsFor(ts, area.relativeToAbs(target.name.getBeginning()), target.name.length(), target.name.getText().substring(0, rCurPos - target.name.getBeginning()), !target.hasAssignment());
		}

		// If we got this far, we're either in a value, or really confused.
		// try and return valid values or bail?
		if (a.value != null && (a.value.contains(rCurPos) || (target.hasAssignment() && area.relativeCursorPos(cursorPos) > a.name.getBeginning())))
			return attributeValidValuesFor(ts, a, area, cursorPos);
		return attributeCompletionsFor(ts, cursorPos, 0, "", true); //$NON-NLS-1$
	}

	/**
	 * @return valid values for the attribute
	 */
	private IJavaCompletionProposal[] attributeValidValuesFor(TagSpec ts, Attribute a, AnnotationArea area, int cursorPos) {
		TagAttribSpec tas = ts.attributeNamed(a.name.getText());
		if (tas == null)
			return null;
		String[] validValues = getValidValues(tas, a, area);
		String partialValue = calculatePartialValue(a, area, cursorPos);
		int valueOffset = calculateValueOffset(a, area, cursorPos);
		if (validValues == null || validValues.length == 0)
			return createCustomAttributeCompletionProposals(ts, tas, partialValue, valueOffset, a.value.getText(), area.javaElement);
		return createAttributeCompletionProposals(partialValue, valueOffset, validValues);
	}

	/**
	 * @param ts
	 * @param tas
	 * @param partialValue
	 * @param valueOffset
	 * @param value
	 * @param javaElement
	 * @return
	 */
	private IJavaCompletionProposal[] createCustomAttributeCompletionProposals(TagSpec ts, TagAttribSpec tas, String partialValue, int valueOffset, String value, IJavaElement javaElement) {
		AttributeValuesHelper helper = ts.getValidValuesHelper();
		if (helper == null)
			return null;
		AttributeValueProposalHelper[] proposalHelpers = helper.getAttributeValueProposalHelpers(tas, partialValue, valueOffset, javaElement);
		if (proposalHelpers == null || proposalHelpers.length == 0)
			return null;
		IJavaCompletionProposal[] proposals = new IJavaCompletionProposal[proposalHelpers.length];
		AnnotationTagProposal proposal;
		for (int i = 0; i < proposalHelpers.length; i++) {
			proposal = new AnnotationTagProposal(proposalHelpers[i]);
			//proposal.setPartialValueString(partialValue);
			proposals[i] = proposal;
		}
		return proposals;
	}

	private IJavaCompletionProposal[] createAttributeCompletionProposals(String partialValue, int valueOffset, String[] validValues) {
		List resultingValues = new ArrayList();
		for (int i = 0; i < validValues.length; i++) {
			String rplString = validValues[i];
			if (partialValue != null && !rplString.startsWith(partialValue))
				continue;
			AnnotationTagProposal prop = new AnnotationTagProposal(rplString, valueOffset, 0, null, rplString, 1);
			prop.setEnsureQuoted(true);
			//prop.setPartialValueString(partialValue);
			resultingValues.add(prop);
		}
		if (resultingValues.isEmpty())
			return null;
		return (IJavaCompletionProposal[]) resultingValues.toArray(new IJavaCompletionProposal[resultingValues.size()]);
	}

	private String[] getValidValues(TagAttribSpec tas, Attribute a, AnnotationArea area) {
		String[] validValues = tas.getValidValues();
		if (validValues == null || validValues.length == 0) {
			AttributeValuesHelper helper = tas.getTagSpec().getValidValuesHelper();
			if (helper == null)
				return null;
			validValues = helper.getValidValues(tas, area.javaElement);
			if ((validValues == null || validValues.length == 0) && tas.valueIsBool())
				validValues = BOOLEAN_VALID_VALUES;
		}
		return validValues;
	}

	/**
	 * @param a
	 * @param area
	 * @param cursorPos
	 * @return
	 */
	private int calculateValueOffset(Attribute a, AnnotationArea area, int cursorPos) {
		if (a.value == null)
			return cursorPos;
		int nameEnd = a.name.getEnd();
		int valBeg = a.value.getBeginning();
		if (valBeg > nameEnd + 2)
			return area.relativeToAbs(nameEnd + 2); //Value too far away to be correct.
		return area.relativeToAbs(valBeg);
	}

	/**
	 * @param a
	 * @param area
	 * @param cursorPos
	 * @return
	 */
	private String calculatePartialValue(Attribute a, AnnotationArea area, int cursorPos) {
		if (a.value == null)
			return null;
		int nameEnd = a.name.getEnd();
		int valueBeg = a.value.getBeginning();
		if (valueBeg > nameEnd + 2)
			return null; //Value is too far away so it must not be part of this attribute.
		int relativePos = area.relativeCursorPos(cursorPos);
		if (a.value.contains(relativePos)) {
			boolean hasBeginQuote = valueBeg - nameEnd == 2;
			String value = a.value.getText();
			int end = relativePos - valueBeg;
			if (hasBeginQuote)
				end--;
			if (end > -1) {
				int length = value.length();
				if (end < length)
					return value.substring(0, end);
				else if (end == length)
					return value;
			}
		}
		return null;
	}

	/**
	 * @param tagName
	 * @return
	 */
	private TagSpec getTagSpecForTagName(String tagName) {
		String simpleName = tagName;
		if (tagName != null && tagName.length() > 0 && tagName.charAt(0) == '@')
			simpleName = tagName.length() == 2 ? "" : tagName.substring(1); //$NON-NLS-1$
		switch (m_tagScope) {
			case TagSpec.TYPE :
				return AnnotationTagRegistry.getTypeTag(simpleName);
			case TagSpec.METHOD :
				return AnnotationTagRegistry.getMethodTag(simpleName);
			case TagSpec.FIELD :
				return AnnotationTagRegistry.getFieldTag(simpleName);
		}
		return null;
	}

	private IJavaCompletionProposal[] attributeCompletionsFor(TagSpec ts, int replaceOffset, int replaceLength, String partialAttributeName, boolean appendEquals) {
		Iterator i = ts.getAttributes().iterator();
		List props = new ArrayList();
		while (i.hasNext()) {
			TagAttribSpec tas = (TagAttribSpec) i.next();
			String aname = tas.getAttribName();

			// Don't suggest attributes that have already been specified.
			if (!m_attSet.contains(aname)) {
				if (aname.startsWith(partialAttributeName)) {
					String rtxt = appendEquals ? aname + '=' : aname;
					AnnotationTagProposal prop = new AnnotationTagProposal(rtxt, replaceOffset, replaceLength, null, aname, 1);
					prop.setHelpText(lookupAttHelp(tas));
					props.add(prop);
				}
			}
		}
		if (props.isEmpty()) {
			return null;
		}
		return (IJavaCompletionProposal[]) props.toArray(new IJavaCompletionProposal[props.size()]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.ws.rd.annotations.TagParseEventHandler#annotationTag(com.ibm.ws.rd.annotations.Token)
	 */
	public void annotationTag(Token tag) {
		m_tagName = tag;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.ws.rd.annotations.TagParseEventHandler#endOfTag(int)
	 */
	public void endOfTag(int pos) {
		// Do nothing
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.ws.rd.annotations.TagParseEventHandler#attribute(com.ibm.ws.rd.annotations.Token,
	 *      int, com.ibm.ws.rd.annotations.Token)
	 */
	public void attribute(Token name, int equalsPosition, Token value) {
		m_attributes.add(new Attribute(name, equalsPosition, value));
		m_attSet.add(name.getText());
	}

	private String getReplacementForTag(TagSpec ts, int beginIndex) {
		StringBuffer bud = new StringBuffer(32);

		bud.append('@');
		bud.append(ts.getTagName());

		String prefix = getArrayPrefixForMultipleAttribs(beginIndex);
		List attributes = ts.getAttributes();

		for (int i = 0; i < attributes.size(); i++) {
			TagAttribSpec tas = (TagAttribSpec) attributes.get(i);

			if (tas.isRequired()) {
				bud.append(prefix);
				bud.append(tas.getAttribName());
				bud.append('=');
			}
		}
		return bud.toString();
	}

	private String getArrayPrefixForMultipleAttribs(int beginIndex) {
		String result = null;
		String source = null;
		// Get source from compilation unit
		try {
			source = m_icu.getSource();
			if (source == null || beginIndex < 0)
				return result;
			// trim off everything after our begin index
			source = source.substring(0, beginIndex + 1);
			int newLineIndex = source.lastIndexOf('\n');
			//if we are on first line...
			if (newLineIndex == -1)
				newLineIndex = 0;
			// Get the current line
			String currentLine = source.substring(newLineIndex, beginIndex + 1);
			// Currently we have to have the '@' sign to show our menu
			int annotationIndex = currentLine.lastIndexOf('@');
			result = currentLine.substring(0, annotationIndex);
			result = result + "  "; //$NON-NLS-1$
		} catch (Exception e) {
			// Do nothing
		}

		return result;
	}

	private IJavaCompletionProposal[] getTagCompletionsFor(String partialTagName, AnnotationArea area, int selectLength) {
		List found = new ArrayList();

		for (int i = 0; i < m_tags.size(); i++) {
			TagSpec ts = (TagSpec) m_tags.get(i);
			String tname = ts.getTagName();

			if (ts.getScope() == m_tagScope && tname.startsWith(partialTagName)) {
				String rtxt = getReplacementForTag(ts, area.beginOffset);
				String labl = '@' + tname;
				AnnotationTagProposal prop = new AnnotationTagProposal(rtxt, area.beginOffset, Math.max(selectLength, rtxt.length()), null, labl, 1);
				prop.setHelpText(lookupTagHelp(ts));
				found.add(prop);
			}
		}

		if (!found.isEmpty()) {
			return (IJavaCompletionProposal[]) found.toArray(new IJavaCompletionProposal[found.size()]);
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jdt.ui.text.java.IJavadocCompletionProcessor#getErrorMessage()
	 */
	public String getErrorMessage() {
		// TODO Auto-generated method stub
		return null;
	}

	private static boolean isWS1(char c) {
		return c == ' ' || c == '\t' || c == '*' || c == '\r' || c == '\n';
	}

	private String getTagSoFarIfNotCompleted(int startingAt, int cursorAt) throws BadLocationException {
		if (m_doc.getChar(startingAt) != '@') {
			return null;
		}

		int firstChar = startingAt + 1;

		if (firstChar == cursorAt) {
			return ""; //$NON-NLS-1$
		}

		for (int i = firstChar; i < cursorAt; i++) {
			char c = m_doc.getChar(i);

			if (isWS1(c)) {
				return null;
			}
		}

		return m_doc.get(firstChar, cursorAt - firstChar);
	}

	/**
	 * Calculates the the area of the annotation we're trying to complete. Also initializes
	 * m_tagScope.
	 * 
	 * @param fromOffset
	 * @return
	 * @throws JavaModelException
	 */
	private AnnotationArea getAnnotationArea(int fromOffset) throws JavaModelException {
		// First, roughly calculate the end of the comment.
		IJavaElement el = m_icu.getElementAt(fromOffset);
		int absmax, absmin;
		if (el == null)
			return null;
		int ty = el.getElementType();

		switch (ty) {
			case IJavaElement.FIELD :
				IField f = (IField) el;
				absmax = f.getNameRange().getOffset();
				absmin = f.getSourceRange().getOffset();
				m_tagScope = TagSpec.FIELD;
				break;

			case IJavaElement.TYPE :
				IType t = (IType) el;
				absmax = t.getNameRange().getOffset();
				absmin = t.getSourceRange().getOffset();
				m_tagScope = TagSpec.TYPE;
				break;

			case IJavaElement.METHOD :
				IMethod m = (IMethod) el;
				absmax = m.getNameRange().getOffset();
				absmin = m.getSourceRange().getOffset();
				m_tagScope = TagSpec.METHOD;
				break;

			default :
				m_tagScope = -1;
				return null;
		}

		// Make sure we're not after the name for the member.
		if (absmax < fromOffset) {
			return null;
		}

		int min = 0, max = 0;
		try {
			// Search backwards for the starting '@'.
			boolean found = false;
			for (min = fromOffset; min >= absmin; min--) {
				if (m_doc.getChar(min) == '@') {
					found = true;
					break;
				}
			}
			if (!found) {
				return null;
			}

			// Search forwards for the next '@', or the end of the comment.
			for (max = fromOffset + 1; max < absmax; max++) {
				if (m_doc.getChar(max) == '@') {
					break;
				}
			}
		} catch (BadLocationException e) {
			return null;
		}

		return new AnnotationArea(el, min, Math.min(absmax, max));
	}

	private String lookupTagHelp(TagSpec ts) {
		if (ts != null)
			try {
				return ts.lookupTagHelp();
			} catch (MissingResourceException e) {
				// Do nothing, return null
			}
		return null;
	}

	private String lookupAttHelp(TagAttribSpec tas) {
		if (tas != null)
			try {
				return tas.lookupTagHelp();
			} catch (MissingResourceException e) {
				// Do nothing, return null
			}
		return null;
	}

	/**
	 * A range that goes from the beginning position up to, but not including, the end position.
	 */
	private static class AnnotationArea {
		/**
		 * Document offset of the beginning of the javadoc annotation.
		 */
		int beginOffset;

		/**
		 * Document offset of the end of the area that could contain an annotation.
		 */
		int endOffset;
		/**
		 * The Java element that this annotation is assigned.
		 * 
		 * @param beg
		 * @param end
		 */
		IJavaElement javaElement;

		public AnnotationArea(IJavaElement javaElement, int beg, int end) {
			this.javaElement = javaElement;
			beginOffset = beg;
			endOffset = end;
		}

		public boolean contains(int offset) {
			return offset >= beginOffset && offset < endOffset;
		}

		public int length() {
			return endOffset - beginOffset;
		}

		/**
		 * Returns the cursor position relative to the area. Only valid if
		 * <code>this.contains( absCursorPos )</code>
		 * 
		 * @param absCursorPos
		 * @return
		 */
		public int relativeCursorPos(int absCursorPos) {
			return absCursorPos - beginOffset;
		}

		public int relativeToAbs(int relPos) {
			return beginOffset + relPos;
		}
	}

	private static class Attribute {
		Token name;

		Token value;

		int equalsPos;

		Attribute(Token n, int ep, Token v) {
			name = n;
			value = v;
			equalsPos = ep;
		}

		public boolean hasAssignment() {
			return equalsPos != -1;
		}

		public boolean hasValue() {
			return value.length() != 0;
		}

		public boolean contains(int srcPos) {
			return srcPos >= minExtent() && srcPos <= maxExtent();
		}

		public int minExtent() {
			return name.getBeginning();
		}

		public int maxExtent() {
			if (hasAssignment()) {
				if (hasValue())
					return value.getEnd();
				return equalsPos;
			}
			return name.getEnd();
		}

		public boolean immediatelyPrecedes(int pos) {
			return maxExtent() + 1 == pos;
		}
	}

}