package com.intellij.lang.javascript.uml.actions;
import com.intellij.diagram.DiagramBuilder;
import com.intellij.diagram.DiagramNode;
import com.intellij.diagram.actions.DiagramCreateNewElementAction;
import com.intellij.ide.util.DirectoryChooserUtil;
import com.intellij.ide.util.PlatformPackageUtil;
import com.intellij.javascript.flex.resolve.ActionScriptClassResolver;
import com.intellij.lang.javascript.psi.ecmal4.JSClass;
import com.intellij.lang.javascript.uml.FlashUmlDataModel;
import com.intellij.lang.javascript.validation.fixes.CreateClassParameters;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.graph.base.Node;
import com.intellij.openapi.graph.builder.util.GraphViewUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.impl.DirectoryIndex;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collection;
import java.util.List;
public abstract class NewJSClassUmlActionBase extends DiagramCreateNewElementAction<Object, CreateClassParameters> {
protected NewJSClassUmlActionBase(String name, String description, Icon icon) {
super(name, description, icon);
}
static JSClass getSuperClass(final CreateClassParameters params) {
final JSClass superClass;
if (params.getSuperclassFqn() != null) {
Module module = ModuleUtilCore.findModuleForPsiElement(params.getTargetDirectory());
GlobalSearchScope superClassScope = module != null
? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)
: GlobalSearchScope.projectScope(params.getTargetDirectory().getProject());
PsiElement byQName = ActionScriptClassResolver.findClassByQNameStatic(params.getSuperclassFqn(), superClassScope);
superClass = byQName instanceof JSClass ? (JSClass)byQName : null;
}
else {
superClass = null;
}
return superClass;
}
@Override
public boolean isEnabled(AnActionEvent e, DiagramBuilder b) {
return b != null && b.getDataModel() instanceof FlashUmlDataModel;
}
@Override
@Nullable
public CreateClassParameters prepare(AnActionEvent e) {
DiagramBuilder diagramBuilder = getBuilder(e);
if (diagramBuilder == null) return null;
final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
if (project == null) {
return null;
}
Pair<PsiDirectory, String> dirAndPackage = getPackageToCreateIn((FlashUmlDataModel)diagramBuilder.getDataModel());
if (dirAndPackage.first == null) {
Collection<VirtualFile> dirs =
DirectoryIndex.getInstance(project).getDirectoriesByPackageName(dirAndPackage.second, false).findAll();
final PsiManager psiManager = PsiManager.getInstance(project);
PsiDirectory[] psiDirs = ContainerUtil.map2Array(dirs, PsiDirectory.class, virtualFile -> psiManager.findDirectory(virtualFile));
PsiDirectory dir = DirectoryChooserUtil.selectDirectory(project, psiDirs, null, null);
if (dir == null) {
return null;
}
dirAndPackage = Pair.create(dir, dirAndPackage.second);
}
return showDialog(project, dirAndPackage);
}
@Nullable
protected abstract CreateClassParameters showDialog(Project project, Pair<PsiDirectory, String> dirAndPackage);
private static Pair<PsiDirectory, String> getPackageToCreateIn(FlashUmlDataModel model) {
final DiagramBuilder builder = model.getBuilder();
String aPackage = null;
PsiDirectory directory = null;
final List<Node> nodes = GraphViewUtil.getSelectedNodes(builder.getGraph());
if (nodes.size() == 1) {
DiagramNode node = builder.getNodeObject(nodes.get(0));
if (node != null) {
if (node.getIdentifyingElement() instanceof String) {
aPackage = (String)node.getIdentifyingElement();
directory = null;
}
else {
final JSClass selectedClass = (JSClass)node.getIdentifyingElement();
directory = PlatformPackageUtil.getDirectory(selectedClass);
aPackage = StringUtil.getPackageName(selectedClass.getQualifiedName());
}
}
}
if (aPackage == null) {
JSClass initialClass = (JSClass)model.getInitialElement();
if (initialClass != null) {
directory = PlatformPackageUtil.getDirectory(initialClass);
aPackage = StringUtil.getPackageName(initialClass.getQualifiedName());
}
else {
directory = null;
aPackage = model.getInitialPackage();
}
}
return Pair.create(directory, aPackage);
}
}