/*
 * 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.
 */
package com.intellij.ide.favoritesTreeView.smartPointerPsiNodes;

import java.util.ArrayList;
import java.util.Collection;

import javax.annotation.Nonnull;

import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.ProjectViewNodeDecorator;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.navigation.NavigationItem;
import com.intellij.navigation.PsiElementNavigationItem;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiDocCommentOwner;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.psi.util.PsiUtilCore;
import consulo.ide.IconDescriptorUpdaters;
import consulo.ide.projectView.impl.nodes.PackageElement;
import consulo.ui.image.Image;

public abstract class BaseSmartPointerPsiNode <Type extends SmartPsiElementPointer> extends ProjectViewNode<Type> implements
                                                                                                                  PsiElementNavigationItem {
  private static final Logger LOG = Logger.getInstance("#com.intellij.ide.projectView.impl.nodes.BasePsiNode");

  protected BaseSmartPointerPsiNode(Project project, Type value, ViewSettings viewSettings) {
    super(project, value, viewSettings);
  }

  @Override
  @Nonnull
  public final Collection<AbstractTreeNode> getChildren() {
    PsiElement value = getPsiElement();
    if (value == null) return new ArrayList<AbstractTreeNode>();
    LOG.assertTrue(value.isValid());
    return getChildrenImpl();
  }

  @Nonnull
  protected abstract Collection<AbstractTreeNode> getChildrenImpl();

  protected boolean isMarkReadOnly() {
    final Object parentValue = getParentValue();
    return parentValue instanceof PsiDirectory || parentValue instanceof PackageElement;
  }

  @Override
  public PsiElement getTargetElement() {
    VirtualFile file = getVirtualFileForValue();
    if (file == null) {
      return null;
    }
    else {
      return file.isDirectory() ? PsiManager.getInstance(getProject()).findDirectory(file) : PsiManager.getInstance(getProject()).findFile(file);
    }
  }

  private VirtualFile getVirtualFileForValue() {
    PsiElement value = getPsiElement();
    if (value == null) return null;
    return PsiUtilCore.getVirtualFile(value);
  }
  // Should be called in atomic action

  protected abstract void updateImpl(PresentationData data);


  @Override
  public void update(PresentationData data) {
    final PsiElement value = getPsiElement();
    if (value == null || !value.isValid()) {
      setValue(null);
    }
    if (getPsiElement() == null) return;

    int flags = Iconable.ICON_FLAG_VISIBILITY;
    if (isMarkReadOnly()) {
      flags |= Iconable.ICON_FLAG_READ_STATUS;
    }

    LOG.assertTrue(value.isValid());

    Image icon = IconDescriptorUpdaters.getIcon(value, flags);
    data.setIcon(icon);
    data.setPresentableText(myName);
    if (isDeprecated()) {
      data.setAttributesKey(CodeInsightColors.DEPRECATED_ATTRIBUTES);
    }
    updateImpl(data);
    for(ProjectViewNodeDecorator decorator: Extensions.getExtensions(ProjectViewNodeDecorator.EP_NAME, myProject)) {
      decorator.decorate(this, data);
    }
  }

  private boolean isDeprecated() {
    final PsiElement element = getPsiElement();
    return element instanceof PsiDocCommentOwner
           && element.isValid()
           && ((PsiDocCommentOwner)element).isDeprecated();
  }

  @Override
  public boolean contains(@Nonnull VirtualFile file) {
    if (getPsiElement() == null) return false;
    PsiFile containingFile = getPsiElement().getContainingFile();
    return file.equals(containingFile.getVirtualFile());
  }

  @Override
  public void navigate(boolean requestFocus) {
    if (canNavigate()) {
      ((NavigationItem)getPsiElement()).navigate(requestFocus);
    }
  }

  @Override
  public boolean canNavigate() {
    return getPsiElement() instanceof NavigationItem && ((NavigationItem)getPsiElement()).canNavigate();
  }

  @Override
  public boolean canNavigateToSource() {
    return getPsiElement() instanceof NavigationItem && ((NavigationItem)getPsiElement()).canNavigateToSource();
  }

  protected PsiElement getPsiElement(){
    final Type value = getValue();
    return value == null ? null : value.getElement();
  }
}

@@ -664,100 +664,8 @@
 s;%0A%0A
-import java.util.ArrayList;%0Aimport java.util.Collection;%0A%0Aimport javax.annotation.Nonnull;%0A%0A
 impo
@@ -714,16 +714,16 @@
 onData;%0A
+
 import c
@@ -1043,55 +1043,8 @@
 em;%0A
-import com.intellij.openapi.diagnostic.Logger;%0A
 impo
@@ -1104,59 +1104,8 @@
 rs;%0A
-import com.intellij.openapi.extensions.Extensions;%0A
 impo
@@ -1261,217 +1261,9 @@
 psi.
-PsiDirectory;%0Aimport com.intellij.psi.PsiDocCommentOwner;%0Aimport com.intellij.psi.PsiElement;%0Aimport com.intellij.psi.PsiFile;%0Aimport com.intellij.psi.PsiManager;%0Aimport com.intellij.psi.SmartPsiElementPointer
+*
 ;%0Aim
@@ -1403,16 +1403,47 @@
 lement;%0A
+import consulo.logging.Logger;%0A
 import c
@@ -1466,16 +1466,107 @@
 Image;%0A%0A
+import javax.annotation.Nonnull;%0Aimport java.util.ArrayList;%0Aimport java.util.Collection;%0A%0A
 public a
@@ -1882,62 +1882,37 @@
 nce(
-%22#com.intellij.ide.projectView.impl.nodes.BasePsiNode%22
+BaseSmartPointerPsiNode.class
 );%0A%0A
@@ -2218,32 +2218,16 @@
 rayList%3C
-AbstractTreeNode
 %3E();%0A   
@@ -3837,33 +3837,8 @@
 or: 
-Extensions.getExtensions(
 Proj
@@ -3865,18 +3865,34 @@
 .EP_NAME
-, 
+.getExtensionList(
 myProjec
@@ -4950,92 +4950,146 @@
     
-final Type value = getValue();%0A    return value == null ? null : value.getElement();
+//noinspection CastToIncompatibleInterface%0A    return (PsiElement) getValue(); // automatically de-anchorized in AbstractTreeNode.getValue
 %0A  %7D

fix cast to pointer