package com.intellij.lang.javascript.flex.sdk;
import com.intellij.flex.FlexCommonUtils;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.javascript.flex.FlexBundle;
import com.intellij.lang.javascript.flex.flashbuilder.FlashBuilderSdkFinder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.vfs.*;
import com.intellij.util.PathUtil;
import icons.FlexIcons;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class FlexSdkType2 extends SdkType {
public static final String NAME = "Flex SDK Type (new)";
public static final String LAST_SELECTED_FLEX_SDK_HOME_KEY = "last.selected.flex.sdk.home";
public FlexSdkType2() {
super(NAME);
}
@Nullable
public String suggestHomePath() {
final String path = PropertiesComponent.getInstance().getValue(LAST_SELECTED_FLEX_SDK_HOME_KEY);
if (path != null) return PathUtil.getParentPath(path);
final String fbInstallation = FlashBuilderSdkFinder.findFBInstallationPath();
return fbInstallation == null ? null : fbInstallation + "/" + FlashBuilderSdkFinder.SDKS_FOLDER;
}
public boolean isValidSdkHome(final String path) {
if (path == null) {
return false;
}
final VirtualFile sdkHome = LocalFileSystem.getInstance().findFileByPath(path);
if (sdkHome == null || !sdkHome.isDirectory()) {
return false;
}
return FlexSdkUtils.doReadFlexSdkVersion(sdkHome) != null || FlexSdkUtils.doReadAirSdkVersion(sdkHome) != null;
}
public String suggestSdkName(final String currentSdkName, final String sdkHome) {
return PathUtil.getFileName(sdkHome);
}
public AdditionalDataConfigurable createAdditionalDataConfigurable(@NotNull final SdkModel sdkModel, @NotNull final SdkModificator sdkModificator) {
return null;
}
public void saveAdditionalData(@NotNull final SdkAdditionalData additionalData, @NotNull final Element additional) {
}
@NotNull
public String getPresentableName() {
return FlexBundle.message("flex.sdk.presentable.name");
}
@NotNull
public Icon getIconForAddAction() {
return getIcon();
}
@NotNull
public static FlexSdkType2 getInstance() {
return SdkType.findInstance(FlexSdkType2.class);
}
public void setupSdkPaths(@NotNull final Sdk sdk) {
SdkModificator modificator = sdk.getSdkModificator();
setupSdkPaths(sdk.getHomeDirectory(), modificator);
modificator.commitChanges();
}
@NotNull
public Icon getIcon() {
return FlexIcons.Flex.Sdk.Flex_sdk;
}
@NotNull
@Override
public String getHelpTopic() {
return "reference.project.structure.sdk.flex";
}
public boolean isRootTypeApplicable(@NotNull final OrderRootType type) {
return type == OrderRootType.CLASSES || type == OrderRootType.SOURCES || type == JavadocOrderRootType.getInstance();
}
public String getDefaultDocumentationUrl(final @NotNull Sdk sdk) {
return "http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/";
}
public String getVersionString(final String sdkHome) {
final VirtualFile sdkRoot = LocalFileSystem.getInstance().findFileByPath(sdkHome);
final String flexVersion = FlexSdkUtils.doReadFlexSdkVersion(sdkRoot);
if (flexVersion != null) return flexVersion;
final String airVersion = FlexSdkUtils.doReadAirSdkVersion(sdkRoot);
return airVersion != null ? FlexCommonUtils.AIR_SDK_VERSION_PREFIX + airVersion : FlexBundle.message("flex.sdk.version.unknown");
}
private void setupSdkPaths(final VirtualFile sdkRoot, final SdkModificator sdkModificator) {
if (sdkRoot == null || !sdkRoot.isValid()) {
return;
}
PropertiesComponent.getInstance().setValue(LAST_SELECTED_FLEX_SDK_HOME_KEY, sdkRoot.getPath());
sdkRoot.refresh(false, true);
sdkModificator.setVersionString(getVersionString(sdkRoot.getPath()));
final VirtualFile playerDir = ApplicationManager.getApplication().runWriteAction((NullableComputable<VirtualFile>)() -> {
final VirtualFile libsDir = LocalFileSystem.getInstance().refreshAndFindFileByPath(sdkRoot.getPath() + "/frameworks/libs");
if (libsDir != null && libsDir.isDirectory()) {
libsDir.refresh(false, true);
return libsDir.findChild("player");
}
return null;
});
if (playerDir != null) {
FlexSdkUtils.processPlayerglobalSwcFiles(playerDir, playerglobalSwcFile -> {
addSwcRoot(sdkModificator, playerglobalSwcFile);
return true;
});
}
final VirtualFile baseDir = sdkRoot.findChild("frameworks"); // I'm not sure if we need to refresh here
if (baseDir != null && baseDir.isDirectory()) {
// let global lib be in the beginning of the list
addSwcRoots(sdkModificator, baseDir, Collections.singletonList("libs/air/airglobal.swc"), false);
addFlexSdkSwcRoots(sdkModificator, baseDir);
}
final VirtualFile projectsDir = VfsUtil.findRelativeFile("frameworks/projects", sdkRoot);
if (projectsDir != null && projectsDir.isDirectory()) {
findSourceRoots(projectsDir, sdkModificator);
}
}
public static void addFlexSdkSwcRoots(SdkModificator sdkModificator, VirtualFile frameworksDir) {
addSwcRoots(sdkModificator, frameworksDir, Arrays.asList("libs", "libs/mx", "libs/air", "libs/mobile", "themes/Mobile"), true);
}
private static void findSourceRoots(final VirtualFile dir, final SdkModificator sdkModificator) {
VfsUtilCore.visitChildrenRecursively(dir, new VirtualFileVisitor(VirtualFileVisitor.SKIP_ROOT) {
@Override
public boolean visitFile(@NotNull VirtualFile child) {
if (child.isDirectory() && child.getName().equals("src")) {
sdkModificator.addRoot(child, OrderRootType.SOURCES);
return false;
}
return true;
}
});
}
private static void addSwcRoots(final SdkModificator sdkModificator,
final VirtualFile baseDir,
final List<String> libRelativePaths,
final boolean skipAirglobalSwc) {
for (String libRelativePath : libRelativePaths) {
final VirtualFile libFileOrDir = baseDir.findFileByRelativePath(libRelativePath);
if (libFileOrDir != null) {
if (libFileOrDir.isDirectory()) {
for (final VirtualFile libCandidate : libFileOrDir.getChildren()) {
if (!libCandidate.isDirectory() && "swc".equalsIgnoreCase(libCandidate.getExtension())) {
if (!skipAirglobalSwc || !libCandidate.getPath().endsWith("frameworks/libs/air/airglobal.swc")) {
addSwcRoot(sdkModificator, libCandidate);
}
}
}
}
else if ("swc".equalsIgnoreCase(libFileOrDir.getExtension())) {
if (!skipAirglobalSwc || !libFileOrDir.getPath().endsWith("frameworks/libs/air/airglobal.swc")) {
addSwcRoot(sdkModificator, libFileOrDir);
}
}
}
}
}
private static void addSwcRoot(final @NotNull SdkModificator sdkModificator, final @NotNull VirtualFile swcFile) {
final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(swcFile);
if (jarRoot != null) {
sdkModificator.addRoot(jarRoot, OrderRootType.CLASSES);
}
}
}