/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.intellij.psi.impl.source.resolve;

import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.scope.NameHint;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.ListIterator;

public class StaticImportResolveProcessor extends BaseScopeProcessor implements NameHint {
  private final PsiImportStaticReferenceElement myReference;
  private final String myName;
  private final List<JavaResolveResult> myFieldResults = new SmartList<JavaResolveResult>();
  private final List<JavaResolveResult> myClassResult = new SmartList<JavaResolveResult>();
  private final List<JavaResolveResult> myResults = new SmartList<JavaResolveResult>();

  public StaticImportResolveProcessor(@NotNull PsiImportStaticReferenceElement reference) {
    myReference = reference;
    myName = myReference.getReferenceName();
  }

  @Override
  public boolean execute(@NotNull final PsiElement candidate, @NotNull final ResolveState state) {
    if (candidate instanceof PsiMember && ((PsiModifierListOwner)candidate).hasModifierProperty(PsiModifier.STATIC)) {
      if (candidate instanceof PsiField) {
        if (checkDomination((PsiMember)candidate, myFieldResults)) return true;
        myFieldResults.add(new OurResolveResult(candidate, myReference));
      }
      else if (candidate instanceof PsiClass) {
        if (checkDomination((PsiMember)candidate, myClassResult)) return true;
        myClassResult.add(new OurResolveResult(candidate, myReference));
      }
      else {
        myResults.add(new OurResolveResult(candidate, myReference));
      }
    }
    return true;
  }

  private static boolean checkDomination(final PsiMember candidate, final List<JavaResolveResult> results) {
    if (!results.isEmpty()) {
      for (ListIterator<JavaResolveResult> i = results.listIterator(results.size()); i.hasPrevious();) {
        final Domination domination = dominates(candidate, (PsiMember)i.previous().getElement());
        if (domination == Domination.DOMINATED_BY) {
          return true;
        }
        else if (domination == Domination.DOMINATES) {
          i.remove();
        }
      }
    }
    return false;
  }

  private static Domination dominates(final PsiMember member1, final PsiMember member2) {
    final PsiClass class1 = member1.getContainingClass();
    final PsiClass class2 = member2.getContainingClass();
    if (class1 != null && class2 != null) {
      if (class1.isInheritor(class2, true)) {
        return Domination.DOMINATES;
      }
      else if (class2.isInheritor(class1, true)) {
        return Domination.DOMINATED_BY;
      }
    }
    return Domination.EQUAL;
  }

  @Override
  public String getName(@NotNull final ResolveState state) {
    return myName;
  }

  @Override
  public <T> T getHint(@NotNull final Key<T> hintKey) {
    if (hintKey == NameHint.KEY) {
      //noinspection unchecked
      return (T)this;
    }
    return super.getHint(hintKey);
  }

  public JavaResolveResult[] getResults() {
    if (myResults.size() + myFieldResults.size() + myClassResult.size() > 1) {
      filterInvalid(myResults);
      filterInvalid(myFieldResults);
      filterInvalid(myClassResult);
    }
    if (!myFieldResults.isEmpty()) {
      myResults.addAll(myFieldResults);
    }
    if (!myClassResult.isEmpty()) {
      myResults.addAll(myClassResult);
    }
    return myResults.toArray(new JavaResolveResult[myResults.size()]);
  }

  private static void filterInvalid(final List<JavaResolveResult> resultList) {
    if (resultList.isEmpty()) return;
    for (ListIterator<JavaResolveResult> i = resultList.listIterator(resultList.size()); i.hasPrevious();) {
      if (!i.previous().isValidResult()) i.remove();
    }
  }

  private static class OurResolveResult extends CandidateInfo {
    private final PsiImportStaticReferenceElement myReference;

    public OurResolveResult(@NotNull PsiElement candidate, final PsiImportStaticReferenceElement reference) {
      super(candidate, PsiSubstitutor.EMPTY);
      myReference = reference;
    }

    @Override
    public boolean isAccessible() {
      final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(myReference.getProject()).getResolveHelper();
      final PsiElement element = getElement();
      return element instanceof PsiMember && resolveHelper.isAccessible((PsiMember)element, myReference, null);
    }

    @Override
    public boolean isStaticsScopeCorrect() {
      return true;
    }
  }
}
