package com.intellij.flex.uiDesigner;
import com.intellij.flex.util.FlexTestUtils;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.TripleFunction;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.IndexableFileSet;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public final class DesignerTests {
private static String testDataPath;
private static VirtualFile testDataDir;
public static VirtualFile[] configureByFiles(@Nullable VirtualFile rawProjectRoot,
VirtualFile[] files,
@Nullable VirtualFile[] auxiliaryFiles,
Module module,
@Nullable TripleFunction<ModifiableRootModel, VirtualFile, List<String>, Void> moduleInitializer)
throws Exception {
return WriteAction.compute(() -> {
VirtualFile dummyRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
//noinspection ConstantConditions
dummyRoot.refresh(false, false);
final VirtualFile sourceDir = dummyRoot.createChildDirectory(DesignerTests.class, "s");
assert sourceDir != null;
final IndexableFileSet indexableFileSet = new IndexableFileSet() {
@Override
public boolean isInSet(@NotNull final VirtualFile file) {
return file.getFileSystem() == sourceDir.getFileSystem();
}
@Override
public void iterateIndexableFilesIn(@NotNull final VirtualFile file, @NotNull final ContentIterator iterator) {
if (file.isDirectory()) {
for (VirtualFile child : file.getChildren()) {
iterateIndexableFilesIn(child, iterator);
}
}
else {
iterator.processFile(file);
}
}
};
FileBasedIndex.getInstance().registerIndexableSet(indexableFileSet, module.getProject());
Disposer.register(module, new Disposable() {
@Override
public void dispose() {
FileBasedIndex.getInstance().removeIndexableSet(indexableFileSet);
ApplicationManager.getApplication().runWriteAction(() -> {
try {
sourceDir.delete(null);
}
catch (IOException e) {
throw new RuntimeException(e);
}
});
}
});
final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel();
VirtualFile[] toFiles = copyFiles(files, sourceDir, rawProjectRoot);
if (auxiliaryFiles != null) {
copyFiles(auxiliaryFiles, sourceDir, rawProjectRoot);
}
rootModel.addContentEntry(sourceDir).addSourceFolder(sourceDir, false);
final List<String> libs = new ArrayList<>();
if (moduleInitializer != null) {
moduleInitializer.fun(rootModel, sourceDir, libs);
}
rootModel.commit();
for (String path : libs) {
VirtualFile virtualFile = path.charAt(0) != '/' ? getFile("lib", path) : getFile(path);
FlexTestUtils.addLibrary(module, path, virtualFile.getParent().getPath(), virtualFile.getName(), null, null);
}
return toFiles;
});
}
private static VirtualFile[] copyFiles(final VirtualFile[] fromFiles, final VirtualFile toDir, VirtualFile rawProjectRoot)
throws IOException {
final VirtualFile[] toFiles = new VirtualFile[fromFiles.length];
final boolean rootSpecified = rawProjectRoot != null;
for (int i = 0, n = fromFiles.length; i < n; i++) {
VirtualFile fromFile = fromFiles[i];
VirtualFile toP = toDir;
if (rootSpecified) {
final List<String> fromParents = new ArrayList<>(4);
VirtualFile fromP = fromFile.getParent();
if (!Comparing.equal(fromP, rawProjectRoot)) {
do {
fromParents.add(fromP.getName());
}
while (!Comparing.equal((fromP = fromP.getParent()), rawProjectRoot));
for (int j = fromParents.size() - 1; j >= 0; j--) {
toP = toP.createChildDirectory(null, fromParents.get(j));
}
}
}
final VirtualFile toFile = toP.createChildData(null, fromFile.getName());
toFile.setBinaryContent(fromFile.contentsToByteArray());
toFiles[i] = toFile;
}
return toFiles;
}
@NotNull
public static VirtualFile getFile(String path) {
VirtualFile file = path.charAt(0) == '/' ? LocalFileSystem.getInstance().findFileByPath(path) : getTestDataDir().findFileByRelativePath(path);
Assert.assertNotNull(file);
return file;
}
@NotNull
public static VirtualFile getFile(String baseDirectoryName, String relativePath) {
//noinspection ConstantConditions
return getTestDataDir().findChild(baseDirectoryName).findFileByRelativePath(relativePath);
}
public static VirtualFile getTestDataDir() {
if (testDataDir == null) {
testDataDir = LocalFileSystem.getInstance().refreshAndFindFileByPath(DebugPathManager.getFudHome() + "/idea-plugin/testData");
assert testDataDir != null;
testDataDir.refresh(false, true);
}
return testDataDir;
}
public static String getTestDataPath() {
if (testDataPath == null) {
testDataPath = new File(DebugPathManager.getFudHome(), "idea-plugin/testData").getPath();
}
return testDataPath;
}
}