/*******************************************************************************
 * 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 = 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;
		}
	}

}