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

/*
 * Class DebuggerTree
 * @author Jeka
 */
package com.intellij.debugger.ui.impl.watch;

import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerInvocationUtil;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.*;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.settings.ThreadsViewSettings;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.debugger.ui.impl.DebuggerTreeBase;
import com.intellij.debugger.ui.impl.tree.TreeBuilder;
import com.intellij.debugger.ui.impl.tree.TreeBuilderNode;
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
import com.intellij.debugger.ui.tree.NodeDescriptor;
import com.intellij.debugger.ui.tree.render.ArrayRenderer;
import com.intellij.debugger.ui.tree.render.ChildrenBuilder;
import com.intellij.debugger.ui.tree.render.ClassRenderer;
import com.intellij.debugger.ui.tree.render.NodeRenderer;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.SpeedSearchComparator;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.xdebugger.settings.XDebuggerSettingsManager;
import com.sun.jdi.*;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.ExceptionEvent;

import javax.swing.*;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;

public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvider {
  private static final Logger LOG = Logger.getInstance(DebuggerTree.class);
  protected static final Key<Rectangle> VISIBLE_RECT = Key.create("VISIBLE_RECT");

  public static final DataKey<DebuggerTree> DATA_KEY = DataKey.create("DebuggerTree"); 

  protected final NodeManagerImpl myNodeManager;

  private DebuggerContextImpl myDebuggerContext = DebuggerContextImpl.EMPTY_CONTEXT;

  private DebuggerTreeNodeImpl myEditedNode;

  public DebuggerTree(Project project) {
    super(null, project);
    setScrollsOnExpand(false);
    myNodeManager = createNodeManager(project);

    final TreeBuilder model = new TreeBuilder(this) {
      @Override
      public void buildChildren(TreeBuilderNode node) {
        final DebuggerTreeNodeImpl debuggerTreeNode = (DebuggerTreeNodeImpl)node;
        if (debuggerTreeNode.getDescriptor() instanceof DefaultNodeDescriptor) {
          return;
        }
        buildNode(debuggerTreeNode);
      }

      @Override
      public boolean isExpandable(TreeBuilderNode builderNode) {
        return DebuggerTree.this.isExpandable((DebuggerTreeNodeImpl)builderNode);
      }
    };
    model.setRoot(getNodeFactory().getDefaultNode());
    model.addTreeModelListener(new TreeModelListener() {
      @Override
      public void treeNodesChanged(TreeModelEvent event) {
        hideTooltip();
      }

      @Override
      public void treeNodesInserted(TreeModelEvent event) {
        hideTooltip();
      }

      @Override
      public void treeNodesRemoved(TreeModelEvent event) {
        hideTooltip();
      }

      @Override
      public void treeStructureChanged(TreeModelEvent event) {
        hideTooltip();
      }
    });

    setModel(model);

    final TreeSpeedSearch search = new TreeSpeedSearch(this);
    search.setComparator(new SpeedSearchComparator(false));
  }

  protected NodeManagerImpl createNodeManager(Project project) {
    return new NodeManagerImpl(project, this);
  }

  @Override
  public void dispose() {
    myNodeManager.dispose();
    myDebuggerContext = DebuggerContextImpl.EMPTY_CONTEXT;
    super.dispose();
  }

  protected boolean isExpandable(DebuggerTreeNodeImpl node) {
    NodeDescriptorImpl descriptor = node.getDescriptor();
    return descriptor.isExpandable();
  }

  @Override
  public Object getData(String dataId) {
    if (DATA_KEY.is(dataId)) {
      return this;
    }
    return null;
  }


  private void buildNode(final DebuggerTreeNodeImpl node) {
    if (node == null || node.getDescriptor() == null) {
      return;
    }
    final DebugProcessImpl debugProcess = getDebuggerContext().getDebugProcess();
    if (debugProcess != null) {
      DebuggerCommandImpl command = getBuildNodeCommand(node);
      if (command != null) {
        node.add(myNodeManager.createMessageNode(MessageDescriptor.EVALUATING));
        debugProcess.getManagerThread().schedule(command);
      }
    }
  }

  // todo: convert "if" into instance method call
  protected DebuggerCommandImpl getBuildNodeCommand(final DebuggerTreeNodeImpl node) {
    if (node.getDescriptor() instanceof StackFrameDescriptorImpl) {
      return new BuildStackFrameCommand(node);
    }
    else if (node.getDescriptor() instanceof ValueDescriptorImpl) {
      return new BuildValueNodeCommand(node);
    }
    else if (node.getDescriptor() instanceof StaticDescriptorImpl) {
      return new BuildStaticNodeCommand(node);
    }
    else if (node.getDescriptor() instanceof ThreadDescriptorImpl) {
      return new BuildThreadCommand(node);
    }
    else if (node.getDescriptor() instanceof ThreadGroupDescriptorImpl) {
      return new BuildThreadGroupCommand(node);
    }
    LOG.assertTrue(false);
    return null;
  }

  public void saveState(DebuggerTreeNodeImpl node) {
    if (node.getDescriptor() != null) {
      TreePath path = new TreePath(node.getPath());
      node.getDescriptor().myIsExpanded = isExpanded(path);
      node.getDescriptor().myIsSelected = getSelectionModel().isPathSelected(path);
      Rectangle rowBounds = getRowBounds(getRowForPath(path));
      if (rowBounds != null && getVisibleRect().contains(rowBounds)) {
        node.getDescriptor().putUserData(VISIBLE_RECT, getVisibleRect());
        node.getDescriptor().myIsVisible = true;
      }
      else {
        node.getDescriptor().putUserData(VISIBLE_RECT, null);
        node.getDescriptor().myIsVisible = false;
      }
    }

    for (Enumeration e = node.rawChildren(); e.hasMoreElements();) {
      DebuggerTreeNodeImpl child = (DebuggerTreeNodeImpl)e.nextElement();
      saveState(child);
    }
  }

  public void restoreState(DebuggerTreeNodeImpl node) {
    restoreStateImpl(node);
    scrollToVisible(node);
  }

  protected final void scrollToVisible(DebuggerTreeNodeImpl scopeNode) {
    final TreePath rootPath = new TreePath(scopeNode.getPath());
    final int rowCount = getRowCount();
    for (int idx = rowCount - 1; idx >= 0; idx--) {
      final TreePath treePath = getPathForRow(idx);
      if (treePath != null) {
        if (!rootPath.isDescendant(treePath)) {
          continue;
        }
        final DebuggerTreeNodeImpl pathNode = (DebuggerTreeNodeImpl)treePath.getLastPathComponent();
        final NodeDescriptorImpl descriptor = pathNode.getDescriptor();

        if (descriptor != null && descriptor.myIsVisible) {
          final Rectangle visibleRect = descriptor.getUserData(VISIBLE_RECT);
          if (visibleRect != null) {
            // prefer visible rect
            scrollRectToVisible(visibleRect);
          }
          else {
            scrollPathToVisible(treePath);
          }
          break;
        }
      }
    }
  }

  @Override
  public void scrollRectToVisible(Rectangle aRect) {
    // see IDEADEV-432
    aRect.width += aRect.x;
    aRect.x = 0;
    super.scrollRectToVisible(aRect);
  }

  private void restoreStateImpl(DebuggerTreeNodeImpl node) {
    restoreNodeState(node);
    if (node.getDescriptor().myIsExpanded) {
      for (Enumeration e = node.rawChildren(); e.hasMoreElements();) {
        DebuggerTreeNodeImpl child = (DebuggerTreeNodeImpl)e.nextElement();
        restoreStateImpl(child);
      }
    }
  }

  public void restoreState() {
    clearSelection();
    DebuggerTreeNodeImpl root = (DebuggerTreeNodeImpl)getModel().getRoot();
    if (root != null) {
      restoreState(root);
    }
  }

  protected void restoreNodeState(DebuggerTreeNodeImpl node) {
    final NodeDescriptorImpl descriptor = node.getDescriptor();
    if (descriptor != null) {
      if (node.getParent() == null) {
        descriptor.myIsExpanded = true;
      }

      TreePath path = new TreePath(node.getPath());
      if (descriptor.myIsExpanded) {
        expandPath(path);
      }
      if (descriptor.myIsSelected) {
        addSelectionPath(path);
      }
    }
  }

  public NodeManagerImpl getNodeFactory() {
    return myNodeManager;
  }

  public TreeBuilder getMutableModel() {
    return (TreeBuilder)getModel();
  }

  public void removeAllChildren() {
    DebuggerTreeNodeImpl root = (DebuggerTreeNodeImpl)getModel().getRoot();
    root.removeAllChildren();
    treeChanged();
  }

  public void showMessage(MessageDescriptor messageDesc) {
    DebuggerTreeNodeImpl root = getNodeFactory().getDefaultNode();
    getMutableModel().setRoot(root);
    DebuggerTreeNodeImpl message = root.add(messageDesc);
    treeChanged();
    expandPath(new TreePath(message.getPath()));
  }

  public void showMessage(String messageText) {
    showMessage(new MessageDescriptor(messageText));
  }

  public final void treeChanged() {
    DebuggerTreeNodeImpl node = (DebuggerTreeNodeImpl)getModel().getRoot();
    if (node != null) {
      getMutableModel().nodeStructureChanged(node);
      restoreState();
    }
  }

  protected abstract void build(DebuggerContextImpl context);

  protected final void buildWhenPaused(DebuggerContextImpl context, RefreshDebuggerTreeCommand command) {
    DebuggerSession session = context.getDebuggerSession();

    if (ApplicationManager.getApplication().isUnitTestMode() || (session != null && session.getState() == DebuggerSession.STATE_PAUSED)) {
      showMessage(MessageDescriptor.EVALUATING);
      context.getDebugProcess().getManagerThread().schedule(command);
    }
    else {
      showMessage(session != null? session.getStateDescription() : DebuggerBundle.message("status.debug.stopped"));
      if (session == null || session.isStopped()) {
        getNodeFactory().clearHistory(); // save memory by clearing references on JDI objects
      }
    }
  }

  public void rebuild(final DebuggerContextImpl context) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    final DebugProcessImpl process = context.getDebugProcess();
    if (process == null) {
      return; // empty context, no process available yet
    }
    myDebuggerContext = context;
    saveState();
    process.getManagerThread().schedule(new DebuggerCommandImpl() {
      @Override
      protected void action() throws Exception {
        getNodeFactory().setHistoryByContext(context);
      }
      @Override
      public Priority getPriority() {
        return Priority.NORMAL;
      }
    });

    build(context);
  }

  public void saveState() {
    saveState((DebuggerTreeNodeImpl)getModel().getRoot());
  }

  public void onEditorShown(DebuggerTreeNodeImpl node) {
    myEditedNode = node;
    hideTooltip();
  }

  public void onEditorHidden(DebuggerTreeNodeImpl node) {
    if (myEditedNode != null) {
      assert myEditedNode == node;
      myEditedNode = null;
    }
  }

  @Override
  public JComponent createToolTip(MouseEvent e) {
    return myEditedNode != null ? null : super.createToolTip(e);
  }

  protected abstract static class RefreshDebuggerTreeCommand extends SuspendContextCommandImpl {
    private final DebuggerContextImpl myDebuggerContext;

    @Override
    public Priority getPriority() {
      return Priority.NORMAL;
    }

    public RefreshDebuggerTreeCommand(DebuggerContextImpl context) {
      super(context.getSuspendContext());
      myDebuggerContext = context;
    }

    public final DebuggerContextImpl getDebuggerContext() {
      return myDebuggerContext;
    }
  }

  public DebuggerContextImpl getDebuggerContext() {
    return myDebuggerContext;
  }

  public abstract class BuildNodeCommand extends DebuggerContextCommandImpl {
    private final DebuggerTreeNodeImpl myNode;

    protected final List<DebuggerTreeNodeImpl> myChildren = new LinkedList<DebuggerTreeNodeImpl>();

    protected BuildNodeCommand(DebuggerTreeNodeImpl node) {
      super(DebuggerTree.this.getDebuggerContext());
      myNode = node;
    }

    @Override
    public Priority getPriority() {
      return Priority.NORMAL;
    }

    public DebuggerTreeNodeImpl getNode() {
      return myNode;
    }

    protected void updateUI(final boolean scrollToVisible) {
      DebuggerInvocationUtil.swingInvokeLater(getProject(), new Runnable() {
        @Override
        public void run() {
          myNode.removeAllChildren();
          for (DebuggerTreeNodeImpl debuggerTreeNode : myChildren) {
            myNode.add(debuggerTreeNode);
          }
          myNode.childrenChanged(scrollToVisible);
        }
      });
    }
  }

  protected class BuildStackFrameCommand extends BuildNodeCommand {
    public BuildStackFrameCommand(DebuggerTreeNodeImpl stackNode) {
      super(stackNode);
    }

    @Override
    public void threadAction() {
      try {
        final StackFrameDescriptorImpl stackDescriptor = (StackFrameDescriptorImpl)getNode().getDescriptor();
        final StackFrameProxyImpl frame = stackDescriptor.getFrameProxy();

        final DebuggerContextImpl debuggerContext = getDebuggerContext();
        final EvaluationContextImpl evaluationContext = debuggerContext.createEvaluationContext();
        if (!debuggerContext.isEvaluationPossible()) {
          myChildren.add(myNodeManager.createNode(MessageDescriptor.EVALUATION_NOT_POSSIBLE, evaluationContext));
        }

        final Location location = frame.location();
        LOG.assertTrue(location != null);

        final ObjectReference thisObjectReference = frame.thisObject();
        final NodeDescriptor descriptor;
        if (thisObjectReference != null) {
          descriptor = myNodeManager.getThisDescriptor(stackDescriptor, thisObjectReference);
        }
        else {
          descriptor = myNodeManager.getStaticDescriptor(stackDescriptor, location.method().declaringType());
        }
        myChildren.add(myNodeManager.createNode(descriptor, evaluationContext));

        final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
        if (classRenderer.SHOW_VAL_FIELDS_AS_LOCAL_VARIABLES) {
          if (thisObjectReference != null && evaluationContext.getDebugProcess().getVirtualMachineProxy().canGetSyntheticAttribute())  {
            final ReferenceType thisRefType = thisObjectReference.referenceType();
            if (thisRefType instanceof ClassType && thisRefType.equals(location.declaringType()) && thisRefType.name().contains("$")) { // makes sense for nested classes only
              final ClassType clsType = (ClassType)thisRefType;
              final DebugProcessImpl debugProcess = getDebuggerContext().getDebugProcess();
              final VirtualMachineProxyImpl vm = debugProcess.getVirtualMachineProxy();
              for (Field field : clsType.fields()) {
                if ((!vm.canGetSyntheticAttribute() || field.isSynthetic()) && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
                  final FieldDescriptorImpl fieldDescriptor = myNodeManager.getFieldDescriptor(stackDescriptor, thisObjectReference, field);
                  myChildren.add(myNodeManager.createNode(fieldDescriptor, evaluationContext));
                }
              }
            }
          }
        }

        try {
          buildVariables(stackDescriptor, evaluationContext);
          if (XDebuggerSettingsManager.getInstance().getDataViewSettings().isSortValues()) {
            Collections.sort(myChildren, NodeManagerImpl.getNodeComparator());
          }
        }
        catch (EvaluateException e) {
          myChildren.add(myNodeManager.createMessageNode(new MessageDescriptor(e.getMessage())));
        }
        // add last method return value if any
        final Pair<Method, Value> methodValuePair = debuggerContext.getDebugProcess().getLastExecutedMethod();
        if (methodValuePair != null) {
          ValueDescriptorImpl returnValueDescriptor = myNodeManager.getMethodReturnValueDescriptor(stackDescriptor, methodValuePair.getFirst(), methodValuePair.getSecond());
          myChildren.add(1, myNodeManager.createNode(returnValueDescriptor, evaluationContext));
        }
        // add context exceptions
        for (Pair<Breakpoint, Event> pair : DebuggerUtilsEx.getEventDescriptors(getSuspendContext())) {
          final Event debugEvent = pair.getSecond();
          if (debugEvent instanceof ExceptionEvent) {
            final ObjectReference exception = ((ExceptionEvent)debugEvent).exception();
            if (exception != null) {
              final ValueDescriptorImpl exceptionDescriptor = myNodeManager.getThrownExceptionObjectDescriptor(stackDescriptor, exception);
              final DebuggerTreeNodeImpl exceptionNode = myNodeManager.createNode(exceptionDescriptor, evaluationContext);
              myChildren.add(1, exceptionNode);
            }
          }
        }

      }
      catch (EvaluateException e) {
        myChildren.clear();
        myChildren.add(myNodeManager.createMessageNode(new MessageDescriptor(e.getMessage())));
      }
      catch (InvalidStackFrameException e) {
        LOG.info(e);
        myChildren.clear();
        notifyCancelled();
      }
      catch (InternalException e) {
        if (e.errorCode() == 35) {
          myChildren.add(
            myNodeManager.createMessageNode(new MessageDescriptor(DebuggerBundle.message("error.corrupt.debug.info", e.getMessage()))));
        }
        else {
          throw e;
        }
      }

      updateUI(true);
    }

    protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext) throws EvaluateException {
      final StackFrameProxyImpl frame = stackDescriptor.getFrameProxy();
      for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
        final LocalVariableDescriptorImpl localVariableDescriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, local);
        final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(localVariableDescriptor, evaluationContext);
        myChildren.add(variableNode);
      }
    }
  }

  private class BuildValueNodeCommand extends BuildNodeCommand implements ChildrenBuilder {
    public BuildValueNodeCommand(DebuggerTreeNodeImpl node) {
      super(node);
    }

    @Override
    public void threadAction() {
      final DebuggerTreeNodeImpl node = getNode();
      ValueDescriptorImpl descriptor = (ValueDescriptorImpl)node.getDescriptor();
      try {
        final NodeRenderer renderer = descriptor.getRenderer(getSuspendContext().getDebugProcess());
        renderer.buildChildren(descriptor.getValue(), this, getDebuggerContext().createEvaluationContext());
      }
      catch (ObjectCollectedException e) {
        final String message = e.getMessage();
        DebuggerInvocationUtil.swingInvokeLater(getProject(), new Runnable() {
          @Override
          public void run() {
            node.removeAllChildren();
            node.add(getNodeFactory().createMessageNode(
              new MessageDescriptor(DebuggerBundle.message("error.cannot.build.node.children.object.collected", message)))
            );
            node.childrenChanged(false);
          }
        });
      }
    }

    @Override
    public NodeManagerImpl getNodeManager() {

      return myNodeManager;
    }

    @Override
    public NodeManagerImpl getDescriptorManager() {
      return myNodeManager;
    }

    @Override
    public ValueDescriptorImpl getParentDescriptor() {
      return (ValueDescriptorImpl)getNode().getDescriptor();
    }

    @Override
    public void setRemaining(int remaining) {}

    @Override
    public void initChildrenArrayRenderer(ArrayRenderer renderer) {}

    @Override
    public void setChildren(final List<DebuggerTreeNode> children) {
      for (DebuggerTreeNode child : children) {
        if (child instanceof DebuggerTreeNodeImpl) {
          myChildren.add(((DebuggerTreeNodeImpl)child));
        }
      }
      updateUI(false);
    }
  }

  private class BuildStaticNodeCommand extends BuildNodeCommand {
    public BuildStaticNodeCommand(DebuggerTreeNodeImpl node) {
      super(node);
    }

    @Override
    public void threadAction() {
      final StaticDescriptorImpl sd = (StaticDescriptorImpl)getNode().getDescriptor();
      final ReferenceType refType = sd.getType();
      List<Field> fields = refType.allFields();
      for (Field field : fields) {
        if (field.isStatic()) {
          final FieldDescriptorImpl fieldDescriptor = myNodeManager.getFieldDescriptor(sd, null, field);
          final EvaluationContextImpl evaluationContext = getDebuggerContext().createEvaluationContext();
          final DebuggerTreeNodeImpl node = myNodeManager.createNode(fieldDescriptor, evaluationContext);
          myChildren.add(node);
        }
      }

      updateUI(true);
    }
  }

  private class BuildThreadCommand extends BuildNodeCommand {
    public BuildThreadCommand(DebuggerTreeNodeImpl threadNode) {
      super(threadNode);
    }

    @Override
    public void threadAction() {
      ThreadDescriptorImpl threadDescriptor = ((ThreadDescriptorImpl)getNode().getDescriptor());
      ThreadReferenceProxyImpl threadProxy = threadDescriptor.getThreadReference();
      if (!threadProxy.isCollected() && getDebuggerContext().getDebugProcess().getSuspendManager().isSuspended(threadProxy)) {
        int status = threadProxy.status();
        if (!(status == ThreadReference.THREAD_STATUS_UNKNOWN) &&
            !(status == ThreadReference.THREAD_STATUS_NOT_STARTED) &&
            !(status == ThreadReference.THREAD_STATUS_ZOMBIE)) {
          try {
            for (StackFrameProxyImpl stackFrame : threadProxy.frames()) {
              //Method method = stackFrame.location().method();
              //ToDo :check whether is synthetic if (shouldDisplay(method)) {
              myChildren.add(myNodeManager.createNode(myNodeManager.getStackFrameDescriptor(threadDescriptor, stackFrame),
                                                      getDebuggerContext().createEvaluationContext()));
            }
          }
          catch (EvaluateException e) {
            myChildren.clear();
            myChildren.add(myNodeManager.createMessageNode(e.getMessage()));
            LOG.debug(e);
            //LOG.assertTrue(false);
            // if we pause during evaluation of this method the exception is thrown
            //  private static void longMethod(){
            //    try {
            //      Thread.sleep(100000);
            //    } catch (InterruptedException e) {
            //      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            //    }
            //  }
          }
        }
      }
      updateUI(true);
    }
  }

  private class BuildThreadGroupCommand extends DebuggerCommandImpl {
    private final DebuggerTreeNodeImpl myNode;
    protected final List<DebuggerTreeNodeImpl> myChildren = new LinkedList<DebuggerTreeNodeImpl>();

    public BuildThreadGroupCommand(DebuggerTreeNodeImpl node) {
      myNode = node;
    }

    @Override
    protected void action() throws Exception {
      ThreadGroupDescriptorImpl groupDescriptor = (ThreadGroupDescriptorImpl)myNode.getDescriptor();
      ThreadGroupReferenceProxyImpl threadGroup = groupDescriptor.getThreadGroupReference();

      List<ThreadReferenceProxyImpl> threads = new ArrayList<ThreadReferenceProxyImpl>(threadGroup.threads());
      Collections.sort(threads, ThreadReferenceProxyImpl.ourComparator);

      final DebuggerContextImpl debuggerContext = getDebuggerContext();
      final SuspendContextImpl suspendContext = debuggerContext.getSuspendContext();
      final EvaluationContextImpl evaluationContext = suspendContext != null && !suspendContext.isResumed()? debuggerContext.createEvaluationContext() : null;

      boolean showCurrent = ThreadsViewSettings.getInstance().SHOW_CURRENT_THREAD;

      for (final ThreadGroupReferenceProxyImpl group : threadGroup.threadGroups()) {
        if (group != null) {
          DebuggerTreeNodeImpl threadNode =
            myNodeManager.createNode(myNodeManager.getThreadGroupDescriptor(groupDescriptor, group), evaluationContext);

          if (showCurrent && ((ThreadGroupDescriptorImpl)threadNode.getDescriptor()).isCurrent()) {
            myChildren.add(0, threadNode);
          }
          else {
            myChildren.add(threadNode);
          }
        }
      }

      ArrayList<DebuggerTreeNodeImpl> threadNodes = new ArrayList<DebuggerTreeNodeImpl>();

      for (ThreadReferenceProxyImpl thread : threads) {
        if (thread != null) {
          final DebuggerTreeNodeImpl threadNode = myNodeManager.createNode(myNodeManager.getThreadDescriptor(groupDescriptor, thread), evaluationContext);
          if (showCurrent && ((ThreadDescriptorImpl)threadNode.getDescriptor()).isCurrent()) {
            threadNodes.add(0, threadNode);
          }
          else {
            threadNodes.add(threadNode);
          }
        }
      }

      myChildren.addAll(threadNodes);

      updateUI(true);
    }

    protected void updateUI(final boolean scrollToVisible) {
      DebuggerInvocationUtil.swingInvokeLater(getProject(), new Runnable() {
        @Override
        public void run() {
          myNode.removeAllChildren();
          for (DebuggerTreeNodeImpl debuggerTreeNode : myChildren) {
            myNode.add(debuggerTreeNode);
          }
          myNode.childrenChanged(scrollToVisible);
        }
      });
    }
  }

  public void hideTooltip() {
    myTipManager.hideTooltip();
  }
}
