package org.jetbrains.idea.maven.dom.references;

import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.plugins.api.MavenSoftAwareReferenceProvider;

/**
 * @author Sergey Evdokimov
 */
public class MavenDependencyReferenceProvider extends PsiReferenceProvider implements MavenSoftAwareReferenceProvider {

  private boolean mySoft;

  private boolean myCanHasVersion = true;

  @NotNull
  @Override
  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
    ElementManipulator<PsiElement> manipulator = ElementManipulators.getManipulator(element);
    TextRange range = manipulator.getRangeInElement(element);

    String text = range.substring(element.getText());

    int firstDelim = text.indexOf(':');

    if (firstDelim == -1) {
      return new PsiReference[]{
        new GroupReference(element, range, mySoft)
      };
    }

    int secondDelim = text.indexOf(':', firstDelim + 1);

    int start = range.getStartOffset();

    if (secondDelim == -1) {
      return new PsiReference[]{
        new GroupReference(element, new TextRange(start, start + firstDelim), mySoft),
        new ArtifactReference(text.substring(0, firstDelim),
                              element, new TextRange(start + firstDelim + 1, range.getEndOffset()), mySoft)
      };
    }

    return new PsiReference[]{
      new GroupReference(element, new TextRange(start, start + firstDelim), mySoft),

      new ArtifactReference(text.substring(0, firstDelim),
                            element, new TextRange(start + firstDelim + 1, start + secondDelim), mySoft),

      new VersionReference(text.substring(0, firstDelim), text.substring(firstDelim + 1, secondDelim),
                           element, new TextRange(start + secondDelim + 1, range.getEndOffset()), mySoft)
    };
  }

  @Override
  public void setSoft(boolean soft) {
    mySoft = soft;
  }

  public boolean isCanHasVersion() {
    return myCanHasVersion;
  }

  public void setCanHasVersion(boolean canHasVersion) {
    myCanHasVersion = canHasVersion;
  }

  private static class GroupReference extends PsiReferenceBase<PsiElement> {

    public GroupReference(PsiElement element, TextRange range, boolean soft) {
      super(element, range, soft);
    }

    @Nullable
    @Override
    public PsiElement resolve() {
      return null;
    }

    @NotNull
    @Override
    public Object[] getVariants() {
      return MavenProjectIndicesManager.getInstance(getElement().getProject()).getGroupIds().toArray();
    }
  }

  public static class ArtifactReference extends PsiReferenceBase<PsiElement> {

    private final String myGroupId;

    public ArtifactReference(@NotNull String groupId, @NotNull PsiElement element, @NotNull TextRange range, @NotNull boolean soft) {
      super(element, range, soft);
      myGroupId = groupId;
    }

    @Nullable
    @Override
    public PsiElement resolve() {
      return null;
    }

    @NotNull
    @Override
    public Object[] getVariants() {
      if (StringUtil.isEmptyOrSpaces(myGroupId)) return ArrayUtil.EMPTY_OBJECT_ARRAY;

      MavenProjectIndicesManager manager = MavenProjectIndicesManager.getInstance(getElement().getProject());
      return manager.getArtifactIds(myGroupId).toArray();
    }
  }

  public static class VersionReference extends PsiReferenceBase<PsiElement> {

    private final String myGroupId;
    private final String myArtifactId;

    public VersionReference(@NotNull String groupId, @NotNull String artifactId, @NotNull PsiElement element, @NotNull TextRange range, @NotNull boolean soft) {
      super(element, range, soft);
      myGroupId = groupId;
      myArtifactId = artifactId;
    }

    @Nullable
    @Override
    public PsiElement resolve() {
      return null;
    }

    @NotNull
    @Override
    public Object[] getVariants() {
      if (StringUtil.isEmptyOrSpaces(myGroupId) || StringUtil.isEmptyOrSpaces(myArtifactId)) {
        return ArrayUtil.EMPTY_OBJECT_ARRAY;
      }

      MavenProjectIndicesManager manager = MavenProjectIndicesManager.getInstance(getElement().getProject());
      return manager.getVersions(myGroupId, myArtifactId).toArray();
    }
  }
}

@@ -1237,24 +1237,42 @@
 econdDelim =
+ myCanHasVersion ?
  text.indexO
@@ -1293,16 +1293,21 @@
 lim + 1)
+ : -1
 ;%0A%0A    i

Add reference for maven-failsafe-plugin classpathDependencyExcludes parameter (MavenDependencyReferenceProvider)