package com.intellij.compiler.artifacts;

import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementFactory;

import java.io.IOException;

/**
 * @author nik
 */
public abstract class PackagingElementsTestCase extends ArtifactsTestCase {

  protected void assertLayout(PackagingElement element, String expected) {
    ArtifactsTestUtil.assertLayout(element, expected);
  }

  protected static PackagingElementFactory getFactory() {
    return PackagingElementFactory.getInstance();
  }

  protected PackagingElementBuilder root() {
    return new PackagingElementBuilder(getFactory().createArtifactRootElement(), null);
  }

  protected PackagingElementBuilder archive(String name) {
    return new PackagingElementBuilder(getFactory().createArchive(name), null);
  }

  protected PackagingElementBuilder dir(String name) {
    return new PackagingElementBuilder(getFactory().createDirectory(name), null);
  }

  protected VirtualFile createFile(final String name) throws IOException {
    return new WriteAction<VirtualFile>() {
      protected void run(final Result<VirtualFile> result) {
        try {
          result.setResult(myProject.getBaseDir().createChildData(this, name));
        }
        catch (IOException e) {
          throw new AssertionError(e);
        }
      }
    }.execute().getResultObject();
  }

  protected VirtualFile getJDomJar() {
    return JarFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(PathManager.getLibPath()) + "/jdom.jar" +
                                                      JarFileSystem.JAR_SEPARATOR);
  }

  protected Library addProjectLibrary(Module module, String name, VirtualFile... jars) {
    final Library library = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject).createLibrary(name);
    final Library.ModifiableModel libraryModel = library.getModifiableModel();
    for (VirtualFile jar : jars) {
      libraryModel.addRoot(jar, OrderRootType.CLASSES);
    }
    libraryModel.commit();
    final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel();
    rootModel.addLibraryEntry(library);
    rootModel.commit();
    return library;
  }

  protected Library addModuleLibrary(Module module, VirtualFile... jars) {
    final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel();
    final Library library = rootModel.getModuleLibraryTable().createLibrary();
    final Library.ModifiableModel libraryModel = library.getModifiableModel();
    for (VirtualFile jar : jars) {
      libraryModel.addRoot(jar, OrderRootType.CLASSES);
    }
    libraryModel.commit();
    rootModel.commit();
    return library;
  }

  protected class PackagingElementBuilder {
    private CompositePackagingElement<?> myElement;
    private final PackagingElementBuilder myParent;

    private PackagingElementBuilder(CompositePackagingElement<?> element, PackagingElementBuilder parent) {
      myElement = element;
      myParent = parent;
    }

    public CompositePackagingElement<?> build() {
      PackagingElementBuilder builder = this;
      while (builder.myParent != null) {
        builder = builder.myParent;
      }
      return builder.myElement;
    }

    public PackagingElementBuilder file(String path) {
      myElement.addOrFindChild(getFactory().createFileCopyWithParentDirectories(path, "/"));
      return this;
    }

    public PackagingElementBuilder module(Module module) {
      myElement.addOrFindChild(getFactory().createModuleOutput(module));
      return this;
    }

    public PackagingElementBuilder lib(Library library) {
      myElement.addOrFindChildren(getFactory().createLibraryElements(library));
      return this;
    }

    public PackagingElementBuilder artifact(Artifact artifact) {
      myElement.addOrFindChild(getFactory().createArtifactElement(artifact, myProject));
      return this;
    }

    public PackagingElementBuilder archive(String name) {
      final CompositePackagingElement<?> archive = getFactory().createArchive(name);
      return new PackagingElementBuilder(myElement.addOrFindChild(archive), this);
    }

    public PackagingElementBuilder dir(String name) {
      return new PackagingElementBuilder(myElement.addOrFindChild(getFactory().createDirectory(name)), this);
    }

    public PackagingElementBuilder add(PackagingElement<?> element) {
      myElement.addOrFindChild(element);
      return this;
    }

    public PackagingElementBuilder end() {
      return myParent;
    }
  }
}

@@ -542,24 +542,25 @@
 api.
-util.io.FileUtil
+vfs.JarFileSystem
 ;%0Aim
@@ -581,35 +581,37 @@
 lij.openapi.vfs.
-Jar
+Local
 FileSystem;%0Aimpo
@@ -889,16 +889,37 @@
 ctory;%0A%0A
+import java.io.File;%0A
 import j
@@ -2171,214 +2171,308 @@
     
-return JarFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(PathManager.getLib
+final File file = PathManager.findFileInLibDirectory(%22jdom.jar%22);%0A    final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);%0A    assertNotNull(file.getAbsolute
 Path()
-)
  + %22
-/jdom.jar%22 +%0A                                                      JarFileSystem.JAR_SEPARATOR
+ not found%22, virtualFile);%0A    return JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile
 );%0A 

fix tests: search for jars in IDEA_HOME/community/lib folder