/*
 * Copyright 2000-2009 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: max
 * Date: Oct 22, 2001
 * Time: 8:21:36 PM
 * To change template for new class use
 * Code Style | Class Templates options (Tools | IDE Options).
 */
package com.intellij.codeInspection.reference;

import com.intellij.ToolExtensionPoints;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.lang.InspectionExtensionsFactory;
import com.intellij.codeInspection.lang.RefManagerExtension;
import com.intellij.lang.Language;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtilCore;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class RefManagerImpl extends RefManager {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.reference.RefManager");

  private int myLastUsedMask = 256 * 256 * 256 * 4;

  @NotNull
  private final Project myProject;
  private AnalysisScope myScope;
  private RefProject myRefProject;
  private Map<PsiAnchor, RefElement> myRefTable = new THashMap<PsiAnchor, RefElement>();

  private Map<Module, RefModule> myModules;
  private final ProjectIterator myProjectIterator;
  private volatile boolean myDeclarationsFound;
  private final PsiManager myPsiManager;

  private volatile boolean myIsInProcess = false;

  private final List<RefGraphAnnotator> myGraphAnnotators = new ArrayList<RefGraphAnnotator>();
  private GlobalInspectionContext myContext;

  private final Map<Key, RefManagerExtension> myExtensions = new HashMap<Key, RefManagerExtension>();
  private final Map<Language, RefManagerExtension> myLanguageExtensions = new HashMap<Language, RefManagerExtension>();

  private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();

  public RefManagerImpl(@NotNull Project project, @Nullable AnalysisScope scope, @NotNull GlobalInspectionContext context) {
    myDeclarationsFound = false;
    myProject = project;
    myScope = scope;
    myContext = context;
    myPsiManager = PsiManager.getInstance(project);
    myRefProject = new RefProjectImpl(this);
    myProjectIterator = new ProjectIterator();
    for (InspectionExtensionsFactory factory : Extensions.getExtensions(InspectionExtensionsFactory.EP_NAME)) {
      final RefManagerExtension extension = factory.createRefManagerExtension(this);
      if (extension != null) {
        myExtensions.put(extension.getID(), extension);
        myLanguageExtensions.put(extension.getLanguage(), extension);
      }
    }
    if (scope != null) {
      for (Module module : ModuleManager.getInstance(getProject()).getModules()) {
        getRefModule(module);
      }
    }
  }

  @NotNull
  public GlobalInspectionContext getContext() {
    return myContext;
  }

  @Override
  public void iterate(@NotNull RefVisitor visitor) {
    myLock.readLock().lock();
    try {
      for (RefElement refElement : getSortedElements()) {
        refElement.accept(visitor);
      }
      if (myModules != null) {
        for (RefModule refModule : myModules.values()) {
          refModule.accept(visitor);
        }
      }
      for (RefManagerExtension extension : myExtensions.values()) {
        extension.iterate(visitor);
      }
    }
    finally {
      myLock.readLock().unlock();
    }
  }

  public void cleanup() {
    myScope = null;
    myRefProject = null;
    myRefTable = null;
    myModules = null;
    myContext = null;

    myGraphAnnotators.clear();
    for (RefManagerExtension extension : myExtensions.values()) {
      extension.cleanup();
    }
  }

  @Nullable
  @Override
  public AnalysisScope getScope() {
    return myScope;
  }


  public void fireNodeInitialized(RefElement refElement) {
    for (RefGraphAnnotator annotator : myGraphAnnotators) {
      annotator.onInitialize(refElement);
    }
  }

  public void fireNodeMarkedReferenced(RefElement refWhat,
                                       RefElement refFrom,
                                       boolean referencedFromClassInitializer,
                                       final boolean forReading,
                                       final boolean forWriting) {
    for (RefGraphAnnotator annotator : myGraphAnnotators) {
      annotator.onMarkReferenced(refWhat, refFrom, referencedFromClassInitializer, forReading, forWriting);
    }
  }

  public void fireNodeMarkedReferenced(PsiElement what,
                                       PsiElement from,
                                       boolean referencedFromClassInitializer) {
    for (RefGraphAnnotator annotator : myGraphAnnotators) {
      annotator.onMarkReferenced(what, from, referencedFromClassInitializer);
    }
  }

  public void fireBuildReferences(RefElement refElement) {
    for (RefGraphAnnotator annotator : myGraphAnnotators) {
      annotator.onReferencesBuild(refElement);
    }
  }

  public void registerGraphAnnotator(RefGraphAnnotator annotator) {
    myGraphAnnotators.add(annotator);
  }

  @Override
  public int getLastUsedMask() {
    myLastUsedMask *= 2;
    return myLastUsedMask;
  }

  @Override
  public <T> T getExtension(@NotNull final Key<T> key) {
    return (T)myExtensions.get(key);
  }

  @Override
  @Nullable
  public String getType(final RefEntity ref) {
    for (RefManagerExtension extension : myExtensions.values()) {
      final String type = extension.getType(ref);
      if (type != null) return type;
    }
    if (ref instanceof RefFile) {
      return SmartRefElementPointer.FILE;
    }
    if (ref instanceof RefModule) {
      return SmartRefElementPointer.MODULE;
    }
    if (ref instanceof RefProject) {
      return SmartRefElementPointer.PROJECT;
    }
    if (ref instanceof RefDirectory) {
      return SmartRefElementPointer.DIR;
    }
    return null;
  }

  @NotNull
  @Override
  public RefEntity getRefinedElement(@NotNull RefEntity ref) {
    for (RefManagerExtension extension : myExtensions.values()) {
      ref = extension.getRefinedElement(ref);
    }
    return ref;
  }

  @Override
  public Element export(@NotNull RefEntity refEntity, @NotNull final Element element, final int actualLine) {
    refEntity = getRefinedElement(refEntity);

    Element problem = new Element("problem");

    if (refEntity instanceof RefElement) {
      final RefElement refElement = (RefElement)refEntity;
      final SmartPsiElementPointer pointer = refElement.getPointer();
      PsiFile psiFile = pointer.getContainingFile();
      if (psiFile == null) return null;

      Element fileElement = new Element("file");
      Element lineElement = new Element("line");
      final VirtualFile virtualFile = psiFile.getVirtualFile();
      LOG.assertTrue(virtualFile != null);
      fileElement.addContent(virtualFile.getUrl());

      if (actualLine == -1) {
        final Document document = PsiDocumentManager.getInstance(pointer.getProject()).getDocument(psiFile);
        LOG.assertTrue(document != null);
        final Segment range = pointer.getRange();
        lineElement.addContent(String.valueOf(range != null ? document.getLineNumber(range.getStartOffset()) + 1 : -1));
      }
      else {
        lineElement.addContent(String.valueOf(actualLine));
      }

      problem.addContent(fileElement);
      problem.addContent(lineElement);

      appendModule(problem, refElement.getModule());
    }
    else if (refEntity instanceof RefModule) {
      final RefModule refModule = (RefModule)refEntity;
      final VirtualFile moduleFile = refModule.getModule().getModuleFile();
      final Element fileElement = new Element("file");
      fileElement.addContent(moduleFile != null ? moduleFile.getUrl() : refEntity.getName());
      problem.addContent(fileElement);
      appendModule(problem, refModule);
    }

    for (RefManagerExtension extension : myExtensions.values()) {
      extension.export(refEntity, problem);
    }

    new SmartRefElementPointerImpl(refEntity, true).writeExternal(problem);
    element.addContent(problem);
    return problem;
  }

  @Override
  @Nullable
  public String getGroupName(final RefElement entity) {
    for (RefManagerExtension extension : myExtensions.values()) {
      final String groupName = extension.getGroupName(entity);
      if (groupName != null) return groupName;
    }
    return null;
  }

  private static void appendModule(final Element problem, final RefModule refModule) {
    if (refModule != null) {
      Element moduleElement = new Element("module");
      moduleElement.addContent(refModule.getName());
      problem.addContent(moduleElement);
    }
  }

  public void findAllDeclarations() {
    if (!myDeclarationsFound) {
      long before = System.currentTimeMillis();
      final AnalysisScope scope = getScope();
      if (scope != null) {
        scope.accept(myProjectIterator);
      }
      myDeclarationsFound = true;

      LOG.info("Total duration of processing project usages:" + (System.currentTimeMillis() - before));
    }
  }

  public boolean isDeclarationsFound() {
    return myDeclarationsFound;
  }

  public void inspectionReadActionStarted() {
    myIsInProcess = true;
  }

  public void inspectionReadActionFinished() {
    myIsInProcess = false;
  }


  public boolean isInProcess() {
    return myIsInProcess;
  }

  @NotNull
  @Override
  public Project getProject() {
    return myProject;
  }

  @NotNull
  @Override
  public RefProject getRefProject() {
    return myRefProject;
  }

  @NotNull
  public Map<PsiAnchor, RefElement> getRefTable() {
    return myRefTable;
  }

  @NotNull
  public List<RefElement> getSortedElements() {
    LOG.assertTrue(myRefTable != null);
    List<RefElement> answer = new ArrayList<RefElement>(myRefTable.values());
    ContainerUtil.quickSort(answer, new Comparator<RefElement>() {
      @Override
      public int compare(RefElement o1, RefElement o2) {
        VirtualFile v1 = ((RefElementImpl)o1).getVirtualFile();
        VirtualFile v2 = ((RefElementImpl)o2).getVirtualFile();

        return (v1 != null ? v1.hashCode() : 0) - (v2 != null ? v2.hashCode() : 0);
      }
    });

    return answer;
  }

  @NotNull
  @Override
  public PsiManager getPsiManager() {
    return myPsiManager;
  }

  public void removeReference(@NotNull RefElement refElem) {
    myLock.writeLock().lock();
    try {
      final Map<PsiAnchor, RefElement> refTable = getRefTable();
      final PsiElement element = refElem.getElement();
      final RefManagerExtension extension = element != null ? getExtension(element.getLanguage()) : null;
      if (extension != null) {
        extension.removeReference(refElem);
      }

      if (element != null && refTable.remove(ApplicationManager.getApplication().runReadAction(
          new Computable<PsiAnchor>() {
            @Override
            public PsiAnchor compute() {
              return PsiAnchor.create(element);
            }
          }
      )) != null) return;

      //PsiElement may have been invalidated and new one returned by getElement() is different so we need to do this stuff.
      for (PsiAnchor psiElement : refTable.keySet()) {
        if (refTable.get(psiElement) == refElem) {
          refTable.remove(psiElement);
          return;
        }
      }
    }
    finally {
      myLock.writeLock().unlock();
    }
  }

  public void initializeAnnotators() {
    ExtensionPoint<RefGraphAnnotator> point = Extensions.getRootArea().getExtensionPoint(ToolExtensionPoints.INSPECTIONS_GRAPH_ANNOTATOR);
    final RefGraphAnnotator[] graphAnnotators = point.getExtensions();
    for (RefGraphAnnotator annotator : graphAnnotators) {
      registerGraphAnnotator(annotator);
    }
    for (RefGraphAnnotator graphAnnotator : myGraphAnnotators) {
      if (graphAnnotator instanceof RefGraphAnnotatorEx) {
        ((RefGraphAnnotatorEx)graphAnnotator).initialize(this);
      }
    }
  }

  private class ProjectIterator extends PsiElementVisitor {
    @Override
    public void visitElement(PsiElement element) {
      final RefManagerExtension extension = getExtension(element.getLanguage());
      if (extension != null) {
        extension.visitElement(element);
      }
      for (PsiElement aChildren : element.getChildren()) {
        aChildren.accept(this);
      }
    }

    @Override
    public void visitFile(PsiFile file) {
      final VirtualFile virtualFile = file.getVirtualFile();
      if (virtualFile != null) {
        String relative = ProjectUtilCore.displayUrlRelativeToProject(virtualFile, virtualFile.getPresentableUrl(), myProject, true, false);
        myContext.incrementJobDoneAmount(myContext.getStdJobDescriptors().BUILD_GRAPH, relative);
      }
      final FileViewProvider viewProvider = file.getViewProvider();
      final Set<Language> relevantLanguages = viewProvider.getLanguages();
      for (Language language : relevantLanguages) {
        visitElement(viewProvider.getPsi(language));
      }
      myPsiManager.dropResolveCaches();
      InjectedLanguageManager.getInstance(myProject).dropFileCaches(file);
    }
  }

  @Override
  @Nullable
  public RefElement getReference(final PsiElement elem) {
    return getReference(elem, false);
  }

  @Nullable
  public RefElement getReference(final PsiElement elem, final boolean ignoreScope) {
    if (elem == null || !elem.isValid() ||
        elem instanceof LightElement || !(elem instanceof PsiDirectory) && !belongsToScope(elem, ignoreScope)) {
      return null;
    }

    RefElement ref = getFromRefTable(elem);
    if (ref != null) return ref;
    if (!isValidPointForReference()) {
      //LOG.assertTrue(true, "References may become invalid after process is finished");
      return null;
    }

    final RefElementImpl refElement = ApplicationManager.getApplication().runReadAction(new Computable<RefElementImpl>() {
      @Override
      @Nullable
      public RefElementImpl compute() {
        final RefManagerExtension extension = getExtension(elem.getLanguage());
        if (extension != null) {
          final RefElement refElement = extension.createRefElement(elem);
          if (refElement != null) return (RefElementImpl)refElement;
        }
        if (elem instanceof PsiFile) {
          return new RefFileImpl((PsiFile)elem, RefManagerImpl.this);
        }
        if (elem instanceof PsiDirectory) {
          return new RefDirectoryImpl((PsiDirectory)elem, RefManagerImpl.this);
        }
        return null;
      }
    });
    if (refElement == null) return null;

    putToRefTable(elem, refElement);

    ApplicationManager.getApplication().runReadAction(new Runnable() {
      @Override
      public void run() {
        refElement.initialize();
        for (RefManagerExtension extension : myExtensions.values()) {
          extension.onEntityInitialized(refElement, elem);
        }
        fireNodeInitialized(refElement);
      }
    });

    return refElement;
  }

  private RefManagerExtension getExtension(final Language language) {
    return myLanguageExtensions.get(language);
  }

  @Nullable
  @Override
  public
  RefEntity getReference(final String type, final String fqName) {
    for (RefManagerExtension extension : myExtensions.values()) {
      final RefEntity refEntity = extension.getReference(type, fqName);
      if (refEntity != null) return refEntity;
    }
    if (SmartRefElementPointer.FILE.equals(type)) {
      return RefFileImpl.fileFromExternalName(this, fqName);
    }
    if (SmartRefElementPointer.MODULE.equals(type)) {
      return RefModuleImpl.moduleFromName(this, fqName);
    }
    if (SmartRefElementPointer.PROJECT.equals(type)) {
      return getRefProject();
    }
    if (SmartRefElementPointer.DIR.equals(type)) {
      String url = VfsUtilCore.pathToUrl(PathMacroManager.getInstance(getProject()).expandPath(fqName));
      VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
      if (vFile != null) {
        final PsiDirectory dir = PsiManager.getInstance(getProject()).findDirectory(vFile);
        return getReference(dir);
      }
    }
    return null;
  }

  protected RefElement getFromRefTable(final PsiElement element) {
    myLock.readLock().lock();
    try {
      return getRefTable().get(ApplicationManager.getApplication().runReadAction(
          new Computable<PsiAnchor>() {
            @Override
            public PsiAnchor compute() {
              return PsiAnchor.create(element);
            }
          }
      ));
    }
    finally {
      myLock.readLock().unlock();
    }
  }

  protected void putToRefTable(final PsiElement element, final RefElement ref) {
    myLock.writeLock().lock();
    try {
      getRefTable().put(ApplicationManager.getApplication().runReadAction(
          new Computable<PsiAnchor>() {
            @Override
            public PsiAnchor compute() {
              return PsiAnchor.create(element);
            }
          }
      ), ref);
    }
    finally {
      myLock.writeLock().unlock();
    }
  }

  @Override
  public RefModule getRefModule(Module module) {
    if (module == null) {
      return null;
    }
    myLock.readLock().lock();
    try {
      if (myModules != null) {
        RefModule refModule = myModules.get(module);
        if (refModule != null) {
          return refModule;
        }
      }
    }
    finally {
      myLock.readLock().unlock();
    }

    myLock.writeLock().lock();
    try {
      if (myModules == null) {
        myModules = new THashMap<Module, RefModule>();
      }
      final RefModule refModule = new RefModuleImpl(module, this);
      myModules.put(module, refModule);
      return refModule;
    }
    finally {
      myLock.writeLock().unlock();
    }
  }

  @Override
  public boolean belongsToScope(final PsiElement psiElement) {
    return belongsToScope(psiElement, false);
  }

  private boolean belongsToScope(final PsiElement psiElement, final boolean ignoreScope) {
    if (psiElement == null || !psiElement.isValid()) return false;
    if (psiElement instanceof PsiCompiledElement) return false;
    final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
      @Override
      public PsiFile compute() {
        return psiElement.getContainingFile();
      }
    });
    if (containingFile == null) {
      return false;
    }
    for (RefManagerExtension extension : myExtensions.values()) {
      if (!extension.belongsToScope(psiElement)) return false;
    }
    final Boolean inProject = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
      @Override
      public Boolean compute() {
        return psiElement.getManager().isInProject(psiElement);
      }
    });
    return inProject.booleanValue() && (ignoreScope || getScope() == null || getScope().contains(psiElement));
  }

  @Override
  public String getQualifiedName(RefEntity refEntity) {
    if (refEntity == null || refEntity instanceof RefElementImpl && !refEntity.isValid()) {
      return InspectionsBundle.message("inspection.reference.invalid");
    }

    return refEntity.getQualifiedName();
  }

  @Override
  public void removeRefElement(@NotNull RefElement refElement, @NotNull List<RefElement> deletedRefs) {
    List<RefEntity> children = refElement.getChildren();
    if (children != null) {
      RefElement[] refElements = children.toArray(new RefElement[children.size()]);
      for (RefElement refChild : refElements) {
        removeRefElement(refChild, deletedRefs);
      }
    }

    ((RefManagerImpl)refElement.getRefManager()).removeReference(refElement);
    ((RefElementImpl)refElement).referenceRemoved();
    if (!deletedRefs.contains(refElement)) deletedRefs.add(refElement);
  }

  protected boolean isValidPointForReference() {
    return myIsInProcess || ApplicationManager.getApplication().isUnitTestMode();
  }
}
