package com.intellij.packageDependencies.ui;

import com.intellij.ide.IconUtilEx;
import com.intellij.openapi.actionSystem.impl.EmptyIcon;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.pom.Navigatable;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
import java.util.HashSet;
import java.util.Set;

public class PackageDependenciesNode extends DefaultMutableTreeNode implements Navigatable{
  private static final EmptyIcon EMPTY_ICON = EmptyIcon.create(0, IconUtilEx.getEmptyIcon(false).getIconHeight());
  private Set<PsiFile> myRegisteredFiles = new HashSet<PsiFile>();
  private boolean myHasUnmarked = false;
  private boolean myHasMarked = false;
  private boolean myEquals;

  public void setEquals(final boolean equals) {
    myEquals = equals;
  }

  public boolean isEquals() {
    return myEquals;
  }

  public void fillFiles(Set<PsiFile> set, boolean recursively) {
    set.addAll(myRegisteredFiles);
  }

  public void addFile(PsiFile file, boolean isMarked) {
    myRegisteredFiles.add(file);
    updateMarked(!isMarked, isMarked);
  }

  public Icon getOpenIcon() {
    return EMPTY_ICON;
  }

  public Icon getClosedIcon() {
    return EMPTY_ICON;
  }

  public int getWeight() {
    return 0;
  }

  public boolean hasUnmarked() {
    return myHasUnmarked;
  }

  public boolean hasMarked() {
    return myHasMarked;
  }

  public PsiElement getPsiElement() {
    return null;
  }

  public int getContainingFiles(){
    int result = 0;
    for (int i = 0; i < getChildCount(); i++) {
      result += ((PackageDependenciesNode)getChildAt(i)).getContainingFiles();
    }
    return result;
  }

  public String getPresentableFilesCount(){
    final int filesCount = getContainingFiles();
    return filesCount > 0 ? " (" + filesCount + (filesCount > 1 ? " entries" : " entry") + ")" : "";
  }

  public void add(MutableTreeNode newChild) {
    super.add(newChild);
    boolean hasUnmarked = ((PackageDependenciesNode)newChild).hasUnmarked();
    boolean hasMarked = ((PackageDependenciesNode)newChild).hasMarked();
    updateMarked(hasUnmarked, hasMarked);
  }

  private void updateMarked(boolean hasUnmarked, boolean hasMarked) {
    if (hasUnmarked && !myHasUnmarked || hasMarked && !myHasMarked) {
      myHasUnmarked |= hasUnmarked;
      myHasMarked |= hasMarked;
      PackageDependenciesNode parent = ((PackageDependenciesNode)getParent());
      if (parent != null) {
        parent.updateMarked(myHasUnmarked, myHasMarked);
      }
    }
  }

  public void navigate(boolean focus) {
    if (canNavigate()) {
      openTextEditor(focus);
    }
  }

  private Editor openTextEditor(boolean focus) {
    return FileEditorManager.getInstance(getProject()).openTextEditor(getDescriptor(), focus);
  }

  public boolean canNavigate() {
    final OpenFileDescriptor descriptor = getDescriptor();
    return descriptor != null ? descriptor.canNavigate() : false;
  }

  public boolean canNavigateToSource() {
    return canNavigate();
  }

  private Project getProject(){
    if (getPsiElement() == null || getPsiElement().getContainingFile() == null){
      return null;
    }
    return getPsiElement().getContainingFile().getProject();
  }

  private OpenFileDescriptor getDescriptor() {
    if (getProject() == null){
      return null;
    }
    return new OpenFileDescriptor(getProject(), getPsiElement().getContainingFile().getVirtualFile());
  }
}
@@ -333,24 +333,69 @@
 Descriptor;%0A
+import com.intellij.openapi.vfs.VirtualFile;%0A
 import com.i
@@ -649,16 +649,60 @@
 l.Set;%0A%0A
+import org.jetbrains.annotations.Nullable;%0A%0A
 public c
@@ -1726,32 +1726,44 @@
 HasMarked;%0A  %7D%0A%0A
+  @Nullable%0A
   public PsiElem
@@ -2977,24 +2977,36 @@
 %0A    %7D%0A  %7D%0A%0A
+  @Nullable%0A
   private Ed
@@ -3038,24 +3038,115 @@
 an focus) %7B%0A
+    final OpenFileDescriptor descriptor = getDescriptor();%0A    if (descriptor != null) %7B%0A  
     return F
@@ -3203,20 +3203,17 @@
 tEditor(
-getD
+d
 escripto
@@ -3213,18 +3213,16 @@
 scriptor
-()
 , focus)
@@ -3219,24 +3219,47 @@
 or, focus);%0A
+    %7D%0A    return null;%0A
   %7D%0A%0A  publi
@@ -3478,32 +3478,44 @@
 avigate();%0A  %7D%0A%0A
+  @Nullable%0A
   private Projec
@@ -3538,27 +3538,73 @@
     
-if (getPsiElement()
+final PsiElement psiElement = getPsiElement();%0A    if (psiElement
  == 
@@ -3611,20 +3611,17 @@
 null %7C%7C 
-getP
+p
 siElemen
@@ -3613,34 +3613,32 @@
 ll %7C%7C psiElement
-()
 .getContainingFi
@@ -3688,20 +3688,17 @@
  return 
-getP
+p
 siElemen
@@ -3690,34 +3690,32 @@
 eturn psiElement
-()
 .getContainingFi
@@ -3730,32 +3730,44 @@
 Project();%0A  %7D%0A%0A
+  @Nullable%0A
   private OpenFi
@@ -3861,51 +3861,39 @@
     
-return new OpenFileDescriptor(getProject(),
+final VirtualFile virtualFile =
  get
@@ -3941,16 +3941,145 @@
 alFile()
+;%0A    if (virtualFile == null %7C%7C !virtualFile.isValid()) return null;%0A    return new OpenFileDescriptor(getProject(), virtualFile
 );%0A  %7D%0A%7D

fix for non valid virtual files