package jetbrains.mps.ide.depanalyzer;

/*Generated by MPS */

import jetbrains.mps.ide.ui.tree.MPSTree;
import jetbrains.mps.ide.ui.tree.MPSTreeNode;
import jetbrains.mps.ide.ui.tree.TextTreeNode;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.ide.ui.tree.module.ProjectModuleTreeNode;
import jetbrains.mps.ide.ui.tree.smodel.SModelTreeNode;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.ide.ui.tree.smodel.SNodeTreeNode;
import com.intellij.openapi.actionSystem.ActionGroup;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.TreePath;
import org.jetbrains.mps.openapi.module.SRepository;
import jetbrains.mps.ide.ui.tree.module.NamespaceTextNode;
import jetbrains.mps.ide.ui.tree.smodel.PackageNode;
import jetbrains.mps.smodel.ModelReadRunnable;

public class DependencyTree2 extends MPSTree {
  private final DependenciesPanel myParent;
  private DependencyViewerScope myScope;

  public DependencyTree2(DependenciesPanel parent) {
    myParent = parent;
    addTreeSelectionListener(new MyTreeSelectionListener());
  }

  @Override
  protected MPSTreeNode rebuild() {
    TextTreeNode root = new TextTreeNode("root");
    if (myScope != null) {
      for (SModule module : myScope.getModules()) {
        root.add(ProjectModuleTreeNode.createFor(myParent.getProject(), module));
      }
      SModelTreeNode.LongModelNameText modelText = new SModelTreeNode.LongModelNameText();
      for (SModel model : myScope.getModels()) {
        root.add(new SModelTreeNode(model, modelText));
      }
      for (SNode node : myScope.getRoots()) {
        root.add(new SNodeTreeNode(node, null));
      }
    }
    setRootVisible(false);
    setShowsRootHandles(true);
    return root;
  }

  @Override
  protected ActionGroup createPopupActionGroup(MPSTreeNode node) {
    return null;
  }

  public void setContent(DependencyViewerScope scope) {
    myScope = scope;
    rebuildLater();
  }

  private class MyTreeSelectionListener implements TreeSelectionListener {
    public MyTreeSelectionListener() {
    }
    @Override
    public void valueChanged(TreeSelectionEvent event) {
      final TreePath[] paths = getSelectionPaths();
      if (paths == null || paths.length == 0) {
        return;
      }
      final SRepository projectRepo = myParent.getProject().getRepository();
      final DependencyViewerScope scope = new DependencyViewerScope(projectRepo);
      projectRepo.getModelAccess().runReadAction(() -> {
        for (TreePath path : paths) {
          MPSTreeNode node = (MPSTreeNode) path.getLastPathComponent();
          if (node instanceof SModelTreeNode) {
            scope.add(((SModelTreeNode) node).getModel());
          }
          if (node instanceof ProjectModuleTreeNode) {
            scope.add(((ProjectModuleTreeNode) node).getModule());
          }
          if (node instanceof SNodeTreeNode) {
            scope.add(((SNodeTreeNode) node).getSNode());
          }
          if (node instanceof NamespaceTextNode) {
            for (SModule module : ((NamespaceTextNode) node).getModulesUnder()) {
              scope.add(module);
            }
            for (SModel model : ((NamespaceTextNode) node).getModelsUnder()) {
              scope.add(model);
            }
          }
          if (node instanceof PackageNode) {
            for (SNode nodeUnder : ((PackageNode) node).getNodesUnderPackage()) {
              scope.add(nodeUnder);
            }
          }

        }
      });
      myParent.updateTargetsView(scope);
    }
  }

  @Override
  protected void doInit(MPSTreeNode node, Runnable runnable) {
    super.doInit(node, new ModelReadRunnable(myParent.getProject().getModelAccess(), runnable));
  }

  @Override
  protected void runRebuildAction(Runnable rebuildAction, boolean saveExpansion) {
    super.runRebuildAction(new ModelReadRunnable(myParent.getProject().getModelAccess(), rebuildAction), saveExpansion);
  }
}
