/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jetbrains.python.facet;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModifiableModelsProvider;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.impl.OrderEntryUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import consulo.fileTypes.ArchiveFileType;
import consulo.vfs.util.ArchiveVfsUtil;

/**
 * @author yole
 */
public class FacetLibraryConfigurator {
  private FacetLibraryConfigurator() {
  }

  public static void attachLibrary(final Module module, @Nullable final ModifiableRootModel existingModel, final String libraryName, final List<String> paths) {
    final ModifiableModelsProvider modelsProvider = ModifiableModelsProvider.SERVICE.getInstance();
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      public void run() {
        // add all paths to library
        final ModifiableRootModel model = existingModel != null ? existingModel : modelsProvider.getModuleModifiableModel(module);
        final LibraryOrderEntry orderEntry = OrderEntryUtil.findLibraryOrderEntry(model, libraryName);
        if (orderEntry != null) {
          // update existing
          Library lib = orderEntry.getLibrary();
          if (lib != null) {
            fillLibrary(module.getProject(), lib, paths);
            if (existingModel == null) {
              modelsProvider.commitModuleModifiableModel(model);
            }
            return;
          }
        }
        // create new
        final LibraryTable.ModifiableModel projectLibrariesModel = modelsProvider.getLibraryTableModifiableModel(model.getProject());
        Library lib = projectLibrariesModel.createLibrary(libraryName);
        fillLibrary(module.getProject(), lib, paths);
        projectLibrariesModel.commit();
        model.addLibraryEntry(lib);
        if (existingModel == null) {
          modelsProvider.commitModuleModifiableModel(model);
        }
      }
    });
  }

  private static void fillLibrary(Project project, Library lib, List<String> paths) {
    Library.ModifiableModel modifiableModel = lib.getModifiableModel();
    for (String root : lib.getUrls(OrderRootType.CLASSES)) {
      modifiableModel.removeRoot(root, OrderRootType.CLASSES);
    }
    Set<VirtualFile> roots = new HashSet<VirtualFile>();
    ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
    Collections.addAll(roots, rootManager.getContentRoots());
    Collections.addAll(roots, rootManager.getContentSourceRoots());
    if (paths != null) {
      for (String dir : paths) {
        VirtualFile pathEntry = LocalFileSystem.getInstance().findFileByPath(dir);
        if (pathEntry != null && !pathEntry.isDirectory() && pathEntry.getFileType() instanceof ArchiveFileType) {
          pathEntry = ArchiveVfsUtil.getJarRootForLocalFile(pathEntry);
        }
        // buildout includes source root of project in paths; don't add it as library home
        if (pathEntry != null && roots.contains(pathEntry)) {
          continue;
        }
        if (pathEntry != null) {
          modifiableModel.addRoot(pathEntry, OrderRootType.CLASSES);
        }
        else {
          modifiableModel.addRoot("file://"+dir, OrderRootType.CLASSES);
        }
      }
    }
    modifiableModel.commit();
  }

  public static void detachLibrary(final Module module, final String libraryName) {
    final ModifiableModelsProvider modelsProvider = ModifiableModelsProvider.SERVICE.getInstance();
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      public void run() {
        // remove the library
        final ModifiableRootModel model = modelsProvider.getModuleModifiableModel(module);
        OrderEntry entry = OrderEntryUtil.findLibraryOrderEntry(model, libraryName);
        if (entry == null) {
          modelsProvider.disposeModuleModifiableModel(model);
        }
        else {
          model.removeOrderEntry(entry);
          modelsProvider.commitModuleModifiableModel(model);
        }
      }
    });
  }
}

@@ -636,144 +636,8 @@
 t;%0A%0A
-import java.util.Collections;%0Aimport java.util.HashSet;%0Aimport java.util.List;%0Aimport java.util.Set;%0A%0Aimport javax.annotation.Nullable;%0A
 impo
@@ -818,175 +818,49 @@
 ots.
-LibraryOrderEntry;%0Aimport com.intellij.openapi.roots.ModifiableModelsProvider;%0Aimport com.intellij.openapi.roots.ModifiableRootModel;%0Aimport com.intellij.openapi.roots
+*;%0Aimport com.intellij.openapi.roots.impl
 .Ord
@@ -866,16 +866,20 @@
 derEntry
+Util
 ;%0Aimport
@@ -910,130 +910,42 @@
 ots.
-OrderRootType;%0Aimport com.intellij.openapi.roots.ProjectRootManager;%0Aimport com.intellij.openapi.roots.impl.OrderEntryUtil
+impl.libraries.ProjectLibraryTable
 ;%0Aim
@@ -1230,16 +1230,152 @@
 sUtil;%0A%0A
+import javax.annotation.Nullable;%0Aimport java.util.Collections;%0Aimport java.util.HashSet;%0Aimport java.util.List;%0Aimport java.util.Set;%0A%0A
 /**%0A * @
@@ -1639,108 +1639,8 @@
 ) %7B%0A
-    final ModifiableModelsProvider modelsProvider = ModifiableModelsProvider.SERVICE.getInstance();%0A
     
@@ -1855,32 +1855,49 @@
 l : 
-modelsProvider.getModule
+ModuleRootManager.getInstance(module).get
 Modi
@@ -1900,38 +1900,32 @@
 ModifiableModel(
-module
 );%0A        final
@@ -2272,56 +2272,22 @@
     
+ 
 model
-sProvider.commitModuleModifiableModel(model
+.commit(
 );%0A 
@@ -2434,72 +2434,79 @@
 l = 
-modelsProvider.getLibraryTableModifiableModel(model.getProject()
+ProjectLibraryTable.getInstance(model.getProject()).getModifiableModel(
 );%0A 
@@ -2757,56 +2757,22 @@
     
+ 
 model
-sProvider.commitModuleModifiableModel(model
+.commit(
 );%0A 
@@ -4222,108 +4222,8 @@
 ) %7B%0A
-    final ModifiableModelsProvider modelsProvider = ModifiableModelsProvider.SERVICE.getInstance();%0A
     
@@ -4392,32 +4392,49 @@
 l = 
-modelsProvider.getModule
+ModuleRootManager.getInstance(module).get
 Modi
@@ -4445,22 +4445,16 @@
 leModel(
-module
 );%0A     
@@ -4581,52 +4581,17 @@
 odel
-sProvider.disposeModuleModifiableModel(model
+.dispose(
 );%0A 
@@ -4674,51 +4674,16 @@
 odel
-sProvider.commitModuleModifiableModel(model
+.commit(
 );%0A 

drop usage idea proxy class