/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package com.google.gwt.eclipse.core.editors.java.contentassist;

import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.ui.text.java.CompletionProposalCollector;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;

/**
 * Custom collector for JSNI proposals. We need this to convert proposals
 * generated by the JDT into instances of our own {@link JsniCompletionProposal}
 * each of which needs references back to the JDT-generated proposals, as well
 * as information about the location of the auto-completion invocation.
 */
class JsniCompletionProposalCollector extends CompletionProposalCollector {

  public static CompletionProposalCollector createMemberProposalCollector(
      ICompilationUnit cu, int refOffset, int refLength,
      String refQualifiedTypeName) {
    JsniCompletionProposalCollector collector = new JsniCompletionProposalCollector(
        cu, refOffset, refLength);
    collector.setIgnored(CompletionProposal.PACKAGE_REF, true);
    collector.setIgnored(CompletionProposal.TYPE_REF, true);
    collector.setQualifiedTypeName(refQualifiedTypeName);

    return collector;
  }

  public static CompletionProposalCollector createPackageAndTypeProposalCollector(
      ICompilationUnit cu, int refOffset, int refLength) {
    CompletionProposalCollector collector = new JsniCompletionProposalCollector(
        cu, refOffset, refLength);
    collector.setIgnored(CompletionProposal.METHOD_REF, true);
    collector.setIgnored(CompletionProposal.FIELD_REF, true);
    return collector;
  }

  // This is only set for member proposal collectors; it is the fully-qualified
  // type (dot-separated) whose members are being collected.
  private String qualifiedTypeName;

  private final int refLength;

  private final int refOffset;

  private JsniCompletionProposalCollector(ICompilationUnit cu, int refOffset,
      int refLength) {
    super(cu);
    this.refOffset = refOffset;
    this.refLength = refLength;

    setIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, true);
  }

  @Override
  protected IJavaCompletionProposal createJavaCompletionProposal(
      CompletionProposal proposal) {
    IJavaCompletionProposal defaultProposal = super.createJavaCompletionProposal(proposal);

    // For members of inner classes, there's a bug in the JDT which results in
    // the declaration signature of the proposal missing the outer classes, so
    // we have to manually set the signature instead.
    if (proposal.getKind() == CompletionProposal.METHOD_REF
        || proposal.getKind() == CompletionProposal.FIELD_REF) {
      char[] typeSignature = Signature.createTypeSignature(qualifiedTypeName,
          true).toCharArray();
      proposal.setDeclarationSignature(typeSignature);
    }

    return JsniCompletionProposal.create(defaultProposal, proposal,
        getCompilationUnit().getJavaProject(), refOffset, refLength);
  }

  private void setQualifiedTypeName(String qualifiedTypeName) {
    this.qualifiedTypeName = qualifiedTypeName;
  }
}