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

import com.intellij.concurrency.JobLauncher;
import com.intellij.ide.PowerSaveMode;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.RuntimeInterruptedException;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectCoreUtil;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.psi.impl.PersistentIntList;
import com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ConcurrentBitSet;
import com.intellij.util.containers.ConcurrentIntObjectMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
import com.intellij.util.io.storage.HeavyProcessLatch;
import com.intellij.util.messages.MessageBus;
import gnu.trove.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaSourceRootType;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class RefResolveServiceImpl extends RefResolveService implements Runnable, Disposable {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.RefResolveService");
  private final AtomicInteger fileCount = new AtomicInteger();
  private final AtomicLong bytesSize = new AtomicLong();
  private final AtomicLong refCount = new AtomicLong();
  private final PersistentIntList storage;
  private final Deque<VirtualFile> filesToResolve = new ArrayDeque<VirtualFile>();
  private final ConcurrentBitSet fileIsInQueue = new ConcurrentBitSet();
  private final ConcurrentBitSet fileIsResolved;
  private final ApplicationEx myApplication;
  private volatile boolean myDisposed;
  private volatile boolean upToDate;
  private final AtomicInteger enableVetoes = new AtomicInteger();  // number of disable() calls. To enable the service, there should be at least corresponding number of enable() calls.
  private final FileWriter log;
  private final ProjectFileIndex myProjectFileIndex;


  public RefResolveServiceImpl(final Project project,
                               final MessageBus messageBus,
                               final PsiManager psiManager,
                               StartupManager startupManager,
                               ApplicationEx application,
                               ProjectFileIndex projectFileIndex) throws IOException {
    super(project);
    ((FutureTask)resolveProcess).run();
    myApplication = application;
    myProjectFileIndex = projectFileIndex;
    if (ResolveScopeManagerImpl.ENABLED_REF_BACK) {
      File indexFile = new File(getStorageDirectory(), "index");
      File dataFile = new File(getStorageDirectory(), "data");
      fileIsResolved = ConcurrentBitSet.readFrom(new File(getStorageDirectory(), "bitSet"));

      final boolean initial = !indexFile.exists() || !dataFile.exists();
      storage = new PersistentIntList(indexFile, dataFile, initial);
      Disposer.register(this, storage);
      if (!application.isUnitTestMode()) {
        startupManager.runWhenProjectIsInitialized(new Runnable() {
          @Override
          public void run() {
            init(messageBus, psiManager);
          }
        });
      }
      log = new FileWriter(new File(getStorageDirectory(), "log.txt"));
      Disposer.register(this, new Disposable() {
        @Override
        public void dispose() {
          try {
            save();
            log.close();
          }
          catch (IOException e) {
            LOG.error(e);
          }
        }
      });
    }
    else {
      log = null;
      fileIsResolved = null;
      storage = null;
    }
  }

  public static List<VirtualFile> toVf(@NotNull int[] ids) {
    List<VirtualFile> res = new ArrayList<VirtualFile>();
    for (int id : ids) {
      VirtualFile file = PersistentFS.getInstance().findFileById(id);
      if (file != null) {
        res.add(file);
      }
    }
    return res;
  }

  public static String toVfString(@NotNull int[] backIds) {
    List<VirtualFile> list = toVf(backIds);
    return toVfString(list);
  }

  private static String toVfString(@NotNull Collection<VirtualFile> list) {
    List<VirtualFile> sub = new ArrayList<VirtualFile>(list).subList(0, Math.min(list.size(), 100));
    return list.size() + " files: " + StringUtil.join(sub, new Function<VirtualFile, String>() {
      @Override
      public String fun(VirtualFile file) {
        return file.getName();
      }
    }, ", ")+(list.size()==sub.size() ? "" : "...");
  }

  private void init(@NotNull MessageBus messageBus, @NotNull PsiManager psiManager) {
    messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter(){
      @Override
      public void after(@NotNull List<? extends VFileEvent> events) {
        fileCount.set(0);
        List<VirtualFile> files = ContainerUtil.mapNotNull(events, new Function<VFileEvent, VirtualFile>() {
          @Override
          public VirtualFile fun(VFileEvent event) {
            return event.getFile();
          }
        });
        queue(files, "VFS events " + events.size());
      }
    });
    psiManager.addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
      @Override
      public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
        PsiFile file = event.getFile();
        VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
        if (virtualFile != null) {
          queue(Collections.singletonList(virtualFile), event);
        }
      }

      @Override
      public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
        childrenChanged(event);
      }
    });

    messageBus.connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() {
      @Override
      public void enteredDumbMode() {
        disable();
      }

      @Override
      public void exitDumbMode() {
        enable();
      }
    });
    messageBus.connect().subscribe(PowerSaveMode.TOPIC, new PowerSaveMode.Listener() {
      @Override
      public void powerSaveStateChanged() {
        if (PowerSaveMode.isEnabled()) {
          enable();
        }
        else {
          disable();
        }
      }
    });
    myApplication.addApplicationListener(new ApplicationAdapter() {
      @Override
      public void beforeWriteActionStart(Object action) {
        disable();
      }

      @Override
      public void writeActionFinished(Object action) {
        enable();
      }

      @Override
      public void applicationExiting() {
        disable();
      }
    }, this);
    VirtualFileManager.getInstance().addVirtualFileManagerListener(new VirtualFileManagerListener() {
      @Override
      public void beforeRefreshStart(boolean asynchronous) {
        disable();
      }

      @Override
      public void afterRefreshFinish(boolean asynchronous) {
        enable();
      }
    }, this);
    HeavyProcessLatch.INSTANCE.addListener(this, new HeavyProcessLatch.HeavyProcessListener() {
      @Override
      public void processStarted() {
      }

      @Override
      public void processFinished() {
        wakeUp();
      }
    });

    startThread();
  }

  // return true if file was added to queue
  private boolean queueIfNeeded(VirtualFile virtualFile, @NotNull Project project) {
    return toResolve(virtualFile, project) && queueUpdate(virtualFile);
  }

  private boolean toResolve(VirtualFile virtualFile, @NotNull Project project) {
    if (virtualFile != null &&
        virtualFile.isValid() &&
        project.isInitialized() &&
        myProjectFileIndex.isInContent(virtualFile)) {
      if (virtualFile.isDirectory()) return true;
      if (virtualFile.getFileType() == StdFileTypes.JAVA) return true;
      if (virtualFile.getFileType() == StdFileTypes.XML && !ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return true;
    }

    // else mark it as resolved so we will not have to check it again
    if (virtualFile instanceof VirtualFileWithId) {
      int id = getAbsId(virtualFile);
      fileIsResolved.set(id);
    }

    return false;
  }

  @NotNull
  private File getStorageDirectory() {
    String dirName = myProject.getName() + "."+Integer.toHexString(myProject.getPresentableUrl().hashCode());
    File dir = new File(PathManager.getSystemPath(), "refs/" + dirName);
    FileUtil.createDirectory(dir);
    return dir;
  }


  private void log(String m) {
    //System.out.println(m);
    logf(m);
  }

  private void logf(String m) {
    try {
      log.write(DateFormat.getDateTimeInstance().format(new Date()) + " "+m+"    ; gap="+storage.gap+"\n");
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  private void flushLog() {
    try {
      log.flush();
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  // return true if file was added to queue
  private boolean queueUpdate(@NotNull VirtualFile file) {
    synchronized (filesToResolve) {
      if (!(file instanceof VirtualFileWithId)) return false;
      int fileId = getAbsId(file);
      countAndMarkUnresolved(file, new THashSet<VirtualFile>(), true);
      boolean alreadyAdded = fileIsInQueue.set(fileId);
      if (!alreadyAdded) {
        filesToResolve.add(file);
      }
      upToDate = false;
      wakeUpUnderLock();
      return !alreadyAdded;
    }
  }

  private void wakeUp() {
    synchronized (filesToResolve) {
      wakeUpUnderLock();
    }
  }

  private void wakeUpUnderLock() {
    filesToResolve.notifyAll();
  }

  private void waitForQueue() throws InterruptedException {
    synchronized (filesToResolve) {
      filesToResolve.wait(1000);
    }
  }

  private void startThread() {
    new Thread(this, "Ref resolve service").start();
    upToDate = true;
    queueUnresolvedFilesSinceLastRestart();
  }

  private void queueUnresolvedFilesSinceLastRestart() {
    PersistentFS fs = PersistentFS.getInstance();
    int maxId = FSRecords.getMaxId();
    TIntArrayList list = new TIntArrayList();
    for (int id= fileIsResolved.nextClearBit(1); id >= 0 && id < maxId; id = fileIsResolved.nextClearBit(id + 1)) {
      int nextSetBit = fileIsResolved.nextSetBit(id);
      int endOfRun = Math.min(maxId, nextSetBit == -1 ? maxId : nextSetBit);
      do {
        VirtualFile virtualFile = fs.findFileById(id);
        if (queueIfNeeded(virtualFile, myProject)) {
          list.add(id);
        }
      }
      while (++id < endOfRun);
    }
    log("Initially added to resolve " + toVfString(list.toNativeArray()));
  }

  @Override
  public void dispose() {
    myDisposed = true;
  }

  private void save() throws IOException {
    fileIsResolved.writeTo(new File(getStorageDirectory(), "bitSet"));
  }

  private volatile Future<?> resolveProcess = new FutureTask<Object>(EmptyRunnable.getInstance(), null); // write from EDT only
  private volatile ProgressIndicator resolveIndicator = new EmptyProgressIndicator();
  
  @Override
  public void run() {
    while (!myDisposed) {
      boolean isEmpty;
      synchronized (filesToResolve) {
        isEmpty = filesToResolve.isEmpty();
      }
      if (enableVetoes.get() > 0 || isEmpty || !resolveProcess.isDone() || HeavyProcessLatch.INSTANCE.isRunning()) {
        try {
          waitForQueue();
        }
        catch (InterruptedException e) {
          break;
        }
        continue;
      }
      final Set<VirtualFile> files = countFilesToResolve();
      if (files.isEmpty()) continue;

      upToDate = false;

      myApplication.invokeLater(new Runnable() {
        @Override
        public void run() {
          if (!resolveProcess.isDone()) return;
          log("Started to resolve " + files.size() + " files");

          Task.Backgroundable backgroundable = new Task.Backgroundable(myProject, "Resolving files...", true) {
            @Override
            public void run(@NotNull final ProgressIndicator indicator) {
              if (!myApplication.isDisposed()) {
                try {
                  processBatch(indicator, files);
                }
                catch (RuntimeInterruptedException ignore) {
                  // see future.cancel() in disable()
                  int i = 0;
                }
              }
            }
          };
          ProgressIndicator indicator;
          if (files.size() > 1) {
            //show progress
            indicator = new BackgroundableProcessIndicator(backgroundable);
          }
          else {
            indicator = new MyProgress();
          }
          resolveIndicator = indicator;
          resolveProcess = ProgressManagerImpl.runProcessWithProgressAsynchronously(backgroundable, indicator, null);
        }
      }, myProject.getDisposed());

      flushLog();
    }
  }

  private volatile int resolvedInPreviousBatch;
  private void processBatch(@NotNull final ProgressIndicator indicator, @NotNull Set<VirtualFile> files) {
    assert !myApplication.isDispatchThread();
    final int resolvedInPreviousBatch = this.resolvedInPreviousBatch;
    final int totalSize = files.size() + resolvedInPreviousBatch;
    final ConcurrentIntObjectMap<int[]> fileToForwardIds = new StripedLockIntObjectConcurrentHashMap<int[]>();
    final Set<VirtualFile> toProcess = Collections.synchronizedSet(files);
    indicator.setIndeterminate(false);
    ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable)indicator);
    long start = System.currentTimeMillis();
    Processor<VirtualFile> processor = new Processor<VirtualFile>() {
      @Override
      public boolean process(VirtualFile file) {
        double fraction = 1 - toProcess.size() * 1.0 / totalSize;
        indicator.setFraction(fraction);
        try {
          if (file.isDirectory() || !toResolve(file, myProject)) {
            return true;
          }
          int fileId = getAbsId(file);
          int i = totalSize - toProcess.size();
          indicator.setText(i + "/" + totalSize + ": Resolving " + file.getPresentableUrl());
          int[] forwardIds = processFile(file, fileId, indicator);
          if (forwardIds == null) {
            //queueUpdate(file);
            return false;
          }
          toProcess.remove(file);
          fileToForwardIds.put(fileId, forwardIds);
        }
        catch (RuntimeException e) {
          indicator.checkCanceled();
        }
        return true;
      }
    };
    boolean success = true;
    try {
      success = JobLauncher
        .getInstance().invokeConcurrentlyUnderProgress(new ArrayList<VirtualFile>(files), indicator, false, false, processor);
    }
    finally {
      this.resolvedInPreviousBatch = toProcess.isEmpty() ? 0 : totalSize - toProcess.size();
      queue(toProcess, "re-added after fail. success=" + success);
      storeIds(fileToForwardIds);

      long end = System.currentTimeMillis();
      log("Resolved batch of " + (totalSize - toProcess.size()) + " from " + totalSize + " files in " + ((end - start) / 1000) + "sec. (Gap: " + storage.gap+")");
      synchronized (filesToResolve) {
        upToDate = filesToResolve.isEmpty();
        log("upToDate = " + upToDate);
      }
    }
  }

  @NotNull
  private Set<VirtualFile> countFilesToResolve() {
    Set<VirtualFile> set;
    synchronized (filesToResolve) {
      int queuedSize = filesToResolve.size();
      set = new THashSet<VirtualFile>(queuedSize);
      // someone might have cleared this bit to mark file as processed
      for (VirtualFile file : filesToResolve) {
        if (fileIsInQueue.clear(getAbsId(file))) {
          set.add(file);
        }
      }
      filesToResolve.clear();
    }
    return countAndMarkUnresolved(set, false);
  }

  private static int getAbsId(@NotNull VirtualFile file) {
    return Math.abs(((VirtualFileWithId)file).getId());
  }

  @NotNull
  private Set<VirtualFile> countAndMarkUnresolved(@NotNull Collection<VirtualFile> files, boolean inDbOnly) {
    Set<VirtualFile> result = new THashSet<VirtualFile>();
    for (VirtualFile file : files) {
      countAndMarkUnresolved(file, result, inDbOnly);
    }
    return result;
  }

  private void countAndMarkUnresolved(@NotNull VirtualFile file, @NotNull final Set<VirtualFile> result, final boolean inDbOnly) {
    if (file.isDirectory()) {
      VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
        @Override
        public boolean visitFile(@NotNull VirtualFile file) {
          doCountAndMarkUnresolved(file, result);
          return true;
        }

        @Nullable
        @Override
        public Iterable<VirtualFile> getChildrenIterable(@NotNull VirtualFile file) {
          return inDbOnly ? ((NewVirtualFile)file).iterInDbChildren() : null;
        }
      });
    }
    else {
      doCountAndMarkUnresolved(file, result);
    }
  }

  private void doCountAndMarkUnresolved(@NotNull VirtualFile file, @NotNull Set<VirtualFile> result) {
    if (file.isDirectory()) {
      fileIsResolved.set(getAbsId(file));
    }
    else if (toResolve(file, myProject)) {
      result.add(file);
      fileIsResolved.clear(getAbsId(file));
    }
  }

  private void enable() {
    // decrement but only if it's positive
    int vetoes;
    do {
      vetoes = enableVetoes.get();
      if (vetoes == 0) break;
    } while(!enableVetoes.compareAndSet(vetoes, vetoes-1));
    wakeUp();
  }

  private void disable() {
    //resolveIndicator.cancel();
    //resolveProcess.cancel(true);
    enableVetoes.incrementAndGet();
    wakeUp();
  }

  // returns list of resolved files if updated successfully, or null if write action or dumb mode started
  private int[] processFile(@NotNull final VirtualFile file,
                            int fileId,
                            @NotNull final ProgressIndicator indicator) {
    final TIntHashSet forward;
    try {
      forward = calcForwardRefs(file, indicator);
    }
    catch (IndexNotReadyException e) {
      return null;
    }
    catch (ApplicationUtil.CannotRunReadActionException e) {
      return null;
    }
    catch (ProcessCanceledException e) {
      throw e;
    }
    catch (Exception e) {
      log(ExceptionUtil.getThrowableText(e));
      flushLog();
      return null;
    }

    int[] forwardIds = forward.toArray();
    fileIsResolved.set(fileId);
    logf("  ---- "+file.getPresentableUrl() + " processed. forwardIds: "+ toVfString(forwardIds));
    return forwardIds;
  }

  private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) {
    int forwardSize = 0;
    int backwardSize = 0;
    final TIntObjectHashMap<TIntArrayList> fileToBackwardIds = new TIntObjectHashMap<TIntArrayList>(fileToForwardIds.size());
    for (StripedLockIntObjectConcurrentHashMap.IntEntry<int[]> entry : fileToForwardIds.entries()) {
      int fileId = entry.getKey();
      int[] forwardIds = entry.getValue();
      forwardSize += forwardIds.length;
      for (int forwardId : forwardIds) {
        TIntArrayList backIds = fileToBackwardIds.get(forwardId);
        if (backIds == null) {
          backIds = new TIntArrayList();
          fileToBackwardIds.put(forwardId, backIds);
        }
        backIds.add(fileId);
        backwardSize++;
      }
    }
    log("backwardSize = " + backwardSize);
    log("forwardSize = " + forwardSize);
    log("fileToForwardIds.size() = "+fileToForwardIds.size());
    log("fileToBackwardIds.size() = "+fileToBackwardIds.size());
    assert forwardSize == backwardSize;

    // wrap in read action so that sudden quit (in write action) would not interrupt us
    myApplication.runReadAction(new Runnable() {
      @Override
      public void run() {
        fileToBackwardIds.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {
          @Override
          public boolean execute(int fileId, TIntArrayList backIds) {
            storage.addAll(fileId, backIds.toNativeArray());
            return true;
          }
        });
      }
    });
  }


  @NotNull
  private TIntHashSet calcForwardRefs(@NotNull final VirtualFile virtualFile, @NotNull final ProgressIndicator indicator)
    throws IndexNotReadyException, ApplicationUtil.CannotRunReadActionException {
    if (myProject.isDisposed()) throw new ProcessCanceledException();
    if (fileCount.incrementAndGet() % 100 == 0) {
      PsiManager.getInstance(myProject).dropResolveCaches();
      synchronized (storage) {
        storage.flush();
      }
      try {
        log.flush();
      }
      catch (IOException e) {
        LOG.error(e);
      }
    }

    final TIntHashSet forward = new TIntHashSet();

    final PsiFile psiFile = ApplicationUtil.tryRunReadAction(new Computable<PsiFile>() {
      @Override
      public PsiFile compute() {
        return PsiManager.getInstance(myProject).findFile(virtualFile);
      }
    });
    final int fileId = getAbsId(virtualFile);
    if (psiFile != null) {
      bytesSize.addAndGet(virtualFile.getLength());
      final Set<PsiElement> resolved = new THashSet<PsiElement>();
      ApplicationUtil.tryRunReadAction(new Runnable() {
        @Override
        public void run() {
          indicator.checkCanceled();

          if (psiFile instanceof PsiJavaFile) {
            psiFile.accept(new JavaRecursiveElementWalkingVisitor() {
              @Override
              public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
                indicator.checkCanceled();
                resolveReference(reference, resolved);

                super.visitReferenceElement(reference);
              }
            });
          }
          else if (psiFile instanceof XmlFile) {
            psiFile.accept(new XmlRecursiveElementWalkingVisitor() {
              @Override
              public void visitXmlElement(XmlElement element) {
                for (PsiReference reference : element.getReferences()) {
                  indicator.checkCanceled();
                  resolveReference(reference, resolved);
                }
                super.visitXmlElement(element);
              }
            });
          }

          indicator.checkCanceled();
          for (PsiElement element : resolved) {
            PsiFile file = element.getContainingFile();
            addIdAndSuperClasses(file, forward);
          }
        }
      });
    }

    forward.remove(fileId);
    return forward;
  }

  private void resolveReference(@NotNull PsiReference reference, @NotNull Set<PsiElement> resolved) {
    PsiElement element = reference.resolve();
    if (element != null) {
      resolved.add(element);
    }
    refCount.incrementAndGet();
  }

  private static void addIdAndSuperClasses(PsiFile file, @NotNull TIntHashSet forward) {
    if (file instanceof PsiJavaFile && file.getName().equals("Object.class") && ((PsiJavaFile)file).getPackageName().equals("java.lang")) {
      return;
    }
    VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
    if (virtualFile instanceof VirtualFileWithId && forward.add(getAbsId(virtualFile)) && file instanceof PsiClassOwner) {
      for (PsiClass aClass : ((PsiClassOwner)file).getClasses()) {
        for (PsiClass superClass : aClass.getSupers()) {
          addIdAndSuperClasses(superClass.getContainingFile(), forward);
        }
      }
    }
  }

  @Override
  @Nullable
  public int[] getBackwardIds(@NotNull VirtualFileWithId file) {
    if (!upToDate) return null;
    int fileId = getAbsId((VirtualFile)file);
    return storage.get(fileId);
  }

  private String prevLog = "";
  private static final Set<JavaSourceRootType> SOURCE_ROOTS = ContainerUtil.newTroveSet(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE);

  @NotNull
  @Override
  public GlobalSearchScope restrictByBackwardIds(@NotNull final VirtualFile virtualFile, @NotNull GlobalSearchScope scope) {
    final int[] backIds = RefResolveService.getInstance(myProject).getBackwardIds((VirtualFileWithId)virtualFile);
    if (backIds == null) {
      return scope;
    }
    String files = toVfString(backIds);
    String log = "Restricting scope of " + virtualFile.getName() + " to " + files;
    if (!log.equals(prevLog)) {
      log(log);
      flushLog();
      prevLog = log;
    }
    GlobalSearchScope restrictedByBackwardIds = new GlobalSearchScope() {
      @Override
      public boolean contains(@NotNull VirtualFile file) {
        if (!(file instanceof VirtualFileWithId)
            || file.equals(virtualFile)
            || ArrayUtil.indexOf(backIds, getAbsId(file)) != -1) return true;
        return false & !myProjectFileIndex.isUnderSourceRootOfType(file, SOURCE_ROOTS); // filter out source file which we know for sure does not reference the element
      }

      @Override
      public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
        return 0;
      }

      @Override
      public boolean isSearchInModuleContent(@NotNull Module aModule) {
        return true;
      }

      @Override
      public boolean isSearchInLibraries() {
        return false;
      }
    };
    return scope.intersectWith(restrictedByBackwardIds);
  }

  @Override
  public boolean queue(@NotNull Collection<VirtualFile> files, Object reason) {
    if (files.isEmpty()) {
      return false;
    }
    boolean queued = false;
    List<VirtualFile> added = new ArrayList<VirtualFile>(files.size());
    for (VirtualFile file : files) {
      boolean wasAdded = queueIfNeeded(file, myProject);
      if (wasAdded) {
        added.add(file);
      }
      queued |= wasAdded;
    }
    if (queued) {
      log("Queued to resolve (from " + reason + "): " + toVfString(added));
      flushLog();
    }
    return queued;
  }

  private static class MyProgress extends ProgressIndicatorBase implements Disposable{
    @Override
    public void dispose() {
    }
  }
}
