/*
 * Copyright 2000-2014 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 org.jetbrains.plugins.groovy.mvc;

import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.ModifiableModelCommitter;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.roots.ui.configuration.actions.ModuleDeleteProvider;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author peter
 */
public class MvcModuleStructureUtil {
  private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.mvc.MvcModuleStructureUtil");
  @NonNls public static final String PLUGINS_DIRECTORY = "plugins";
  @NonNls public static final String APPLICATION_PROPERTIES = "application.properties";
  public static final Key<String> LAST_MVC_VERSION = Key.create("LAST_MVC_VERSION");

  private MvcModuleStructureUtil() {
  }

  @Nullable
  public static ContentEntry findContentEntry(ModuleRootModel rootModel, VirtualFile root) {
    for (ContentEntry entry : rootModel.getContentEntries()) {
      if (Comparing.equal(entry.getFile(), root)) {
        return entry;
      }
    }

    return null;
  }

  @Nullable
  private static Consumer<ModifiableRootModel> addSourceRootsAndLibDirectory(@NotNull final VirtualFile root,
                                                                             final MvcProjectStructure structure) {
    ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(structure.myModule);

    Map<VirtualFile, JpsModuleSourceRootType<?>> sourceRoots = new HashMap<VirtualFile, JpsModuleSourceRootType<?>>();
    for (ContentEntry entry : moduleRootManager.getContentEntries()) {
      for (SourceFolder folder : entry.getSourceFolders()) {
        sourceRoots.put(folder.getFile(), folder.getRootType());
      }
    }

    root.refresh(false, true);

    final List<Consumer<ContentEntry>> actions = ContainerUtil.newArrayList();

    for (Map.Entry<JpsModuleSourceRootType<?>, Collection<String>> entry : structure.getSourceFolders().entrySet()) {
      JpsModuleSourceRootType<?> rootType = entry.getKey();

      for (String src : entry.getValue()) {
        addSourceFolder(root, src, rootType, actions, sourceRoots);
      }
    }

    for (final String src : structure.getInvalidSourceFolders()) {
      removeSrcFolderFromRoots(root.findFileByRelativePath(src), actions, sourceRoots);
    }

    for (final VirtualFile excluded : structure.getExcludedFolders(root)) {
      if (moduleRootManager.getFileIndex().isInContent(excluded)) {
        actions.add(new Consumer<ContentEntry>() {
          @Override
          public void consume(ContentEntry contentEntry) {
            contentEntry.addExcludeFolder(excluded);
          }
        });
      }
    }

    final Consumer<ModifiableRootModel> modifyLib = addJarDirectory(root, structure.myModule, structure.getUserLibraryName());

    if (actions.isEmpty() && modifyLib == null && findContentEntry(moduleRootManager, root) != null) {
      return null;
    }

    return new Consumer<ModifiableRootModel>() {
      @Override
      public void consume(ModifiableRootModel model) {
        ContentEntry contentEntry = findContentEntry(model, root);
        if (contentEntry == null) {
          contentEntry = model.addContentEntry(root);
        }

        for (final Consumer<ContentEntry> action : actions) {
          action.consume(contentEntry);
        }
        if (modifyLib != null) {
          modifyLib.consume(model);
        }
      }
    };
  }

  public static void removeSrcFolderFromRoots(final VirtualFile file,
                                              @NotNull List<Consumer<ContentEntry>> actions,
                                              @NotNull Map<VirtualFile, JpsModuleSourceRootType<?>> sourceRoots) {
    removeSrcFolderFromRoots(file, actions, sourceRoots.keySet());
  }

  public static void removeSrcFolderFromRoots(final VirtualFile file,
                                              @NotNull List<Consumer<ContentEntry>> actions,
                                              @NotNull Collection<VirtualFile> sourceRoots) {
    if (sourceRoots.contains(file)) {
      actions.add(new Consumer<ContentEntry>() {
        @Override
        public void consume(ContentEntry contentEntry) {
          SourceFolder[] folders = contentEntry.getSourceFolders();
          for (SourceFolder folder : folders) {
            if (Comparing.equal(folder.getFile(), file)) {
              contentEntry.removeSourceFolder(folder);
            }
          }
        }
      });
    }
  }

  @Nullable
  public static Consumer<ModifiableRootModel> addJarDirectory(VirtualFile root, Module module, final String libName) {
    final VirtualFile libDir = root.findFileByRelativePath("lib");
    if (libDir == null || !libDir.isDirectory() || ProjectRootManager.getInstance(module.getProject()).getFileIndex().isExcluded(libDir)) {
      return null;
    }

    final Library library = findUserLibrary(module, libName);
    if (library != null && library.isJarDirectory(libDir.getUrl())) {
      return null;
    }

    return new Consumer<ModifiableRootModel>() {
      @Override
      public void consume(ModifiableRootModel model) {
        Library.ModifiableModel libModel = modifyDefaultLibrary(model, libName);
        libModel.addJarDirectory(libDir, false);
        libModel.commit();
      }
    };
  }

  public static Library.ModifiableModel modifyDefaultLibrary(ModifiableRootModel model, String libName) {
    LibraryTable libTable = model.getModuleLibraryTable();

    for (Library library : libTable.getLibraries()) {
      if (library.getName() != null && library.getName().startsWith(libName)) {
        return library.getModifiableModel();
      }
    }

    Library library = LibraryUtil.createLibrary(libTable, libName + " (" + model.getModule().getName() + ')');

    for (OrderEntry entry : model.getOrderEntries()) {
      if (!(entry instanceof LibraryOrderEntry)) continue;

      LibraryOrderEntry libraryEntry = (LibraryOrderEntry)entry;
      if (libraryEntry.isModuleLevel() && libraryEntry.getLibrary() == library) {
        libraryEntry.setExported(true);
      }
    }

    return library.getModifiableModel();
  }

  private static void addSourceFolder(@NotNull VirtualFile root,
                                      @NotNull String relativePath,
                                      final JpsModuleSourceRootType<?> rootType,
                                      List<Consumer<ContentEntry>> actions,
                                      Map<VirtualFile, JpsModuleSourceRootType<?>> sourceRoots) {
    final VirtualFile src = root.findFileByRelativePath(relativePath);
    if (src == null) {
      return;
    }

    JpsModuleSourceRootType<?> existingRootType = sourceRoots.get(src);

    if (rootType == JavaSourceRootType.TEST_SOURCE && (existingRootType != null && existingRootType != JavaSourceRootType.TEST_SOURCE)) { // see http://youtrack.jetbrains.net/issue/IDEA-70642
      actions.add(new Consumer<ContentEntry>() {
        @Override
        public void consume(ContentEntry entry) {
          for (SourceFolder folder : entry.getSourceFolders()) {
            if (Comparing.equal(folder.getFile(), src)) {
              entry.removeSourceFolder(folder);
              entry.addSourceFolder(src, rootType);
              break;
            }
          }
        }
      });
      return;
    }

    actions.add(new Consumer<ContentEntry>() {
      @Override
      public void consume(ContentEntry contentEntry) {
        contentEntry.addSourceFolder(src, rootType);
      }
    });
  }

  public static void updateModuleStructure(Module module, MvcProjectStructure structure, @NotNull VirtualFile root) {
    List<Consumer<ModifiableRootModel>> actions = getUpdateProjectStructureActions(Collections.singletonList(root), structure);

    if (!actions.isEmpty()) {
      final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
      boolean success = false;
      try {
        for (final Consumer<ModifiableRootModel> action : actions) {
          action.consume(model);
        }
        model.commit();
        success = true;
      }
      finally {
        if (!success) {
          model.dispose();
        }
      }
    }
  }

  private static boolean checkValidity(VirtualFile pluginDir) {
    pluginDir.refresh(false, false);
    return pluginDir.isValid();
  }

  private static List<Consumer<ModifiableRootModel>> getUpdateProjectStructureActions(Collection<VirtualFile> appRoots,
                                                                                      MvcProjectStructure structure) {
    for (final VirtualFile appRoot : ModuleRootManager.getInstance(structure.myModule).getContentRoots()) {
      appRoot.refresh(false, false);
    }

    List<Consumer<ModifiableRootModel>> actions = ContainerUtil.newArrayList();
    removeInvalidSourceRoots(actions, structure);
    cleanupDefaultLibrary(structure.myModule, actions, appRoots, structure.getUserLibraryName());
    moveupLibrariesFromMavenPlugin(structure.myModule, actions);

    List<VirtualFile> rootsToFacetSetup = new ArrayList<VirtualFile>(appRoots.size());
    for (VirtualFile appRoot : appRoots) {
      if (checkValidity(appRoot)) {
        ContainerUtil.addIfNotNull(addSourceRootsAndLibDirectory(appRoot, structure), actions);
        rootsToFacetSetup.add(appRoot);
      }
    }

    List<Runnable> facetActions = new ArrayList<Runnable>();
    structure.setupFacets(facetActions, rootsToFacetSetup);
    for (final Runnable action : facetActions) {
      actions.add(new Consumer<ModifiableRootModel>() {
        @Override
        public void consume(ModifiableRootModel model) {
          action.run();
        }
      });
    }

    return actions;
  }

  @Nullable
  private static OrderEntry[] moveupLibrariesFromMavenPlugin(ModuleRootModel moduleRootModel) {
    LibraryOrderEntry newestLibrary = null;
    int firstLibraryIndex = 0;
    int newestLibraryIndex = 0;

    OrderEntry[] orderEntries = moduleRootModel.getOrderEntries();
    for (int i = 0; i < orderEntries.length; i++) {
      if (orderEntries[i] instanceof LibraryOrderEntry) {
        LibraryOrderEntry libraryEntry = (LibraryOrderEntry)orderEntries[i];
        String libraryName = libraryEntry.getLibraryName();
        if (libraryName != null && libraryName.contains("slf4j-api")) {
          if (newestLibrary == null) {
            newestLibrary = libraryEntry;
            firstLibraryIndex = i;
            newestLibraryIndex = i;
          }
          else {
            if (libraryName.compareTo(newestLibrary.getLibraryName()) > 0) {
              newestLibraryIndex = i;
              newestLibrary = libraryEntry;
            }
          }
        }
      }
    }

    if (firstLibraryIndex == newestLibraryIndex) return null;

    OrderEntry[] res = orderEntries.clone();
    ArrayUtil.swap(res, firstLibraryIndex, newestLibraryIndex);
    return res;
  }

  private static void moveupLibrariesFromMavenPlugin(final Module module, List<Consumer<ModifiableRootModel>> actions) {
    if (moveupLibrariesFromMavenPlugin(ModuleRootManager.getInstance(module)) != null) {
      actions.add(new Consumer<ModifiableRootModel>() {
        @Override
        public void consume(ModifiableRootModel modifiableRootModel) {
          OrderEntry[] orderEntries = moveupLibrariesFromMavenPlugin(modifiableRootModel);
          if (orderEntries != null) {
            modifiableRootModel.rearrangeOrderEntries(orderEntries);
          }
        }
      });
    }
  }

  private static void removeInvalidSourceRoots(List<Consumer<ModifiableRootModel>> actions, MvcProjectStructure structure) {
    final Set<SourceFolder> toRemove = ContainerUtil.newTroveSet();
    final Set<String> toRemoveContent = ContainerUtil.newTroveSet();
    for (ContentEntry entry : ModuleRootManager.getInstance(structure.myModule).getContentEntries()) {
      final VirtualFile file = entry.getFile();
      if (file == null || !structure.isValidContentRoot(file)) {
        toRemoveContent.add(entry.getUrl());
      }
      else {
        for (SourceFolder folder : entry.getSourceFolders()) {
          if (folder.getFile() == null) {
            toRemove.add(folder);
          }
        }
      }
    }

    if (!toRemove.isEmpty() || !toRemoveContent.isEmpty()) {
      actions.add(new Consumer<ModifiableRootModel>() {
        @Override
        public void consume(ModifiableRootModel model) {
          for (ContentEntry entry : model.getContentEntries()) {
            if (toRemoveContent.remove(entry.getUrl())) {
              model.removeContentEntry(entry);
            }
            else {
              for (SourceFolder folder : entry.getSourceFolders()) {
                if (toRemove.remove(folder)) {
                  entry.removeSourceFolder(folder);
                }
              }
            }
          }
        }
      });
    }
  }

  public static void cleanupDefaultLibrary(Module module,
                                           List<Consumer<ModifiableRootModel>> actions,
                                           Collection<VirtualFile> appRoots,
                                           final String libName) {
    final Library library = findUserLibrary(module, libName);
    if (library == null) {
      return;
    }

    final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();

    final List<String> toRemoveUrls = new ArrayList<String>();

    for (String url : library.getUrls(OrderRootType.CLASSES)) {
      VirtualFile virtualFile = virtualFileManager.findFileByUrl(url);

      if (virtualFile == null) {
        toRemoveUrls.add(url);
      }
      else {
        if (library.isJarDirectory(url)) {
          if (!virtualFile.getName().equals("lib") || !appRoots.contains(virtualFile.getParent())) {
            toRemoveUrls.add(url);
          }
        }
      }
    }

    if (!toRemoveUrls.isEmpty()) {
      actions.add(new Consumer<ModifiableRootModel>() {
        @Override
        public void consume(ModifiableRootModel model) {
          final Library.ModifiableModel modifiableModel = modifyDefaultLibrary(model, libName);
          for (String url : toRemoveUrls) {
            modifiableModel.removeRoot(url, OrderRootType.CLASSES);
          }
          modifiableModel.commit();
        }
      });
    }
  }

  public static boolean hasModulesWithSupport(Project project, final MvcFramework framework) {
    for (Module module : ModuleManager.getInstance(project).getModules()) {
      if (framework.hasSupport(module)) {
        return true;
      }
    }

    return false;
  }

  public static List<Module> getAllModulesWithSupport(Project project, MvcFramework framework) {
    List<Module> modules = new ArrayList<Module>();
    for (Module module : ModuleManager.getInstance(project).getModules()) {
      if (framework.hasSupport(module)) {
        modules.add(module);
      }
    }
    return modules;
  }

  @Nullable
  private static Library extractNonModuleLibraries(List<Library> result,
                                                   ModuleRootManager rootManager,
                                                   boolean providedOnly,
                                                   String userLibraryName) {
    Library userLibrary = null;

    for (OrderEntry entry : rootManager.getOrderEntries()) {
      if (entry instanceof LibraryOrderEntry) {
        LibraryOrderEntry libraryEntry = (LibraryOrderEntry)entry;
        Library library = libraryEntry.getLibrary();

        if (library != null) {
          String libraryName = libraryEntry.getLibraryName();
          if (libraryName != null && libraryName.startsWith(userLibraryName)) {
            userLibrary = library;
          }
          else {
            if (library.getTable() != null && (!providedOnly || !libraryEntry.getScope().isForProductionRuntime())) {
              result.add(library);
            }
          }
        }
      }
    }

    return userLibrary;
  }

  private static Set<String> getJarUrls(@Nullable Library library) {
    if (library == null) return Collections.emptySet();

    Set<String> res = new HashSet<String>();

    for (String url : library.getUrls(OrderRootType.CLASSES)) {
      if (!library.isJarDirectory(url)) {
        res.add(url);
      }
    }

    return res;
  }

  public static void syncAuxModuleSdk(@NotNull Module appModule, @NotNull Module pluginsModule, @NotNull final MvcFramework framework) {
    final ModuleRootManager auxRootManager = ModuleRootManager.getInstance(pluginsModule);
    final ModuleRootManager appRootManager = ModuleRootManager.getInstance(appModule);

    final boolean isSdkEquals = Comparing.equal(auxRootManager.getSdk(), appRootManager.getSdk());

    List<Library> appLibraries = new ArrayList<Library>();
    Library appUserLibrary = extractNonModuleLibraries(appLibraries, appRootManager, false, framework.getUserLibraryName());

    List<Library> auxLibraries = new ArrayList<Library>();
    Library auxUserLibrary = extractNonModuleLibraries(auxLibraries, auxRootManager, false, framework.getUserLibraryName());

    final boolean isLibrariesEquals = appLibraries.equals(auxLibraries) && getJarUrls(auxUserLibrary).equals(getJarUrls(appUserLibrary));

    if (!isSdkEquals || !isLibrariesEquals) {
      AccessToken token = WriteAction.start();
      try {
        final ModifiableRootModel model = auxRootManager.getModifiableModel();

        if (!isSdkEquals) {
          copySdk(appRootManager, model);
        }

        if (!isLibrariesEquals) {
          copyUserLibraries(appRootManager, model, framework);
        }

        model.commit();
      }
      finally {
        token.finish();
      }
    }
  }

  @Nullable
  public static PropertiesFile findApplicationProperties(@NotNull Module module, MvcFramework framework) {
    VirtualFile root = framework.findAppRoot(module);
    if (root == null) return null;

    VirtualFile appChild = root.findChild(APPLICATION_PROPERTIES);
    if (appChild == null || !appChild.isValid()) return null;

    PsiManager manager = PsiManager.getInstance(module.getProject());
    PsiFile psiFile = manager.findFile(appChild);
    if (psiFile instanceof PropertiesFile) {
      return (PropertiesFile)psiFile;
    }
    return null;
  }

  public static void removeAuxiliaryModule(Module toRemove) {
    List<ModifiableRootModel> usingModels = new SmartList<ModifiableRootModel>();

    Project project = toRemove.getProject();
    ModuleManager moduleManager = ModuleManager.getInstance(project);

    for (Module module : moduleManager.getModules()) {
      if (module == toRemove) {
        continue;
      }

      ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
      for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
        if (entry instanceof ModuleOrderEntry && toRemove == ((ModuleOrderEntry)entry).getModule()) {
          usingModels.add(moduleRootManager.getModifiableModel());
          break;
        }
      }
    }

    final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel();

    ModuleDeleteProvider.removeModule(toRemove, null, usingModels, moduleModel);

    ModifiableRootModel[] rootModels = usingModels.toArray(new ModifiableRootModel[usingModels.size()]);
    ModifiableModelCommitter.multiCommit(rootModels, moduleModel);
  }

  @NotNull
  public static Module createAuxiliaryModule(@NotNull Module appModule, final String moduleName, final MvcFramework framework) {
    ModuleManager moduleManager = ModuleManager.getInstance(appModule.getProject());
    final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel();
    final String moduleFilePath = new File(appModule.getModuleFilePath()).getParent() + "/" + moduleName + ".iml";
    final VirtualFile existing = LocalFileSystem.getInstance().findFileByPath(moduleFilePath);
    if (existing != null) {
      try {
        existing.delete("Grails/Griffon plugins maintenance");
      }
      catch (IOException e) {
        LOG.error(e);
      }
    }

    moduleModel.newModule(moduleFilePath, StdModuleTypes.JAVA.getId());
    moduleModel.commit();

    Module pluginsModule = moduleManager.findModuleByName(moduleName);
    assert pluginsModule != null;

    ModifiableRootModel newRootModel = ModuleRootManager.getInstance(pluginsModule).getModifiableModel();
    ModifiableRootModel appModel = ModuleRootManager.getInstance(appModule).getModifiableModel();

    copySdkAndLibraries(appModel, newRootModel, framework);

    newRootModel.commit();
    appModel.commit();

    return pluginsModule;
  }

  public static void ensureDependency(@NotNull Module from, @NotNull Module to, boolean exported) {
    if (!from.equals(to) && !hasDependency(from, to)) {
      ModuleRootModificationUtil.addDependency(from, to, DependencyScope.COMPILE, exported);
    }
  }

  public static boolean hasDependency(@NotNull Module from, @NotNull Module to) {
    for (OrderEntry entry : ModuleRootManager.getInstance(from).getOrderEntries()) {
      if (entry instanceof ModuleOrderEntry) {
        final ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
        if (to == moduleOrderEntry.getModule()) {
          return true;
        }
      }
    }
    return false;
  }

  public static void removeDependency(@NotNull Module from, @NotNull Module to) {
    if (!from.equals(to) && hasDependency(from, to)) {
      final ModifiableRootModel fromModel = ModuleRootManager.getInstance(from).getModifiableModel();
      for (OrderEntry entry : fromModel.getOrderEntries()) {
        if (entry instanceof ModuleOrderEntry) {
          final ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
          if (to == moduleOrderEntry.getModule()) {
            fromModel.removeOrderEntry(moduleOrderEntry);
          }
        }
      }
      fromModel.commit();
    }
  }

  public static void copySdk(ModuleRootModel from, ModifiableRootModel to) {
    if (from.isSdkInherited()) {
      to.inheritSdk();
    }
    else {
      to.setSdk(from.getSdk());
    }
  }

  public static void copySdkAndLibraries(ModuleRootModel from, ModifiableRootModel to, @NotNull MvcFramework framework) {
    copySdk(from, to);
    copyUserLibraries(from, to, framework);
  }

  public static void copyUserLibraries(ModuleRootModel from, ModifiableRootModel to, @NotNull MvcFramework framework) {
    Library userLibraryTo = null;

    for (OrderEntry entry : to.getOrderEntries()) {
      if (entry instanceof LibraryOrderEntry) {
        LibraryOrderEntry libraryEntry = (LibraryOrderEntry)entry;
        Library library = libraryEntry.getLibrary();

        if (library != null) {
          String libraryName = libraryEntry.getLibraryName();
          if (libraryName != null && libraryName.startsWith(framework.getUserLibraryName())) {
            userLibraryTo = library;
          }
          else {
            if (library.getTable() != null && (!libraryEntry.getScope().isForProductionRuntime() || framework.isSDKLibrary(library))) {
              to.removeOrderEntry(entry);
            }
          }
        }
      }
    }

    Library userLibraryFrom = null;

    for (OrderEntry entry : from.getOrderEntries()) {
      if (entry instanceof LibraryOrderEntry) {
        LibraryOrderEntry libraryEntry = (LibraryOrderEntry)entry;
        Library library = libraryEntry.getLibrary();

        if (library != null) {
          String libraryName = library.getName();
          if (libraryName != null && libraryName.startsWith(framework.getUserLibraryName())) {
            userLibraryFrom = library;
          }
          else {
            if (library.getTable() != null) {
              LibraryOrderEntry libraryOrderEntry = to.addLibraryEntry(library);
              libraryOrderEntry.setScope(DependencyScope.PROVIDED);
            }
          }
        }
      }
    }

    if (userLibraryTo == null) {
      if (userLibraryFrom == null) return;

      userLibraryTo = to.getModuleLibraryTable().createLibrary(framework.getUserLibraryName() + " (" + to.getModule().getName() + ')');
    }
    else {
      OrderEntry[] orderEntries = to.getOrderEntries().clone();

      for (int i = 0; i < orderEntries.length; i++) {
        OrderEntry orderEntry = orderEntries[i];
        if (orderEntry instanceof LibraryOrderEntry) {
          if (userLibraryTo == ((LibraryOrderEntry)orderEntry).getLibrary()) {
            System.arraycopy(orderEntries, i + 1, orderEntries, i, orderEntries.length - i - 1);
            orderEntries[orderEntries.length - 1] = orderEntry;
            to.rearrangeOrderEntries(orderEntries);
            break;
          }
        }
      }
    }

    Library.ModifiableModel model = userLibraryTo.getModifiableModel();
    for (String url : model.getUrls(OrderRootType.CLASSES)) {
      if (!model.isJarDirectory(url)) {
        model.removeRoot(url, OrderRootType.CLASSES);
      }
    }

    if (userLibraryFrom != null) {
      for (String url : userLibraryFrom.getUrls(OrderRootType.CLASSES)) {
        if (!userLibraryFrom.isJarDirectory(url)) {
          model.addRoot(url, OrderRootType.CLASSES);
        }
      }
    }

    model.commit();
  }

  public static Consumer<ModifiableRootModel> removeStaleContentEntries(final Collection<VirtualFile> pluginDirs) {
    return new Consumer<ModifiableRootModel>() {
      @Override
      public void consume(ModifiableRootModel modifiableRootModel) {
        for (final ContentEntry entry : modifiableRootModel.getContentEntries()) {
          if (!pluginDirs.contains(entry.getFile())) {
            modifiableRootModel.removeContentEntry(entry);
          }
        }
      }
    };
  }

  public static void updateAuxModuleStructure(Module auxModule, Collection<VirtualFile> pluginDirs, MvcFramework framework) {
    final MvcProjectStructure structure = framework.createProjectStructure(auxModule, true);
    final List<Consumer<ModifiableRootModel>> actions = getUpdateProjectStructureActions(pluginDirs, structure);
    for (final ContentEntry root : ModuleRootManager.getInstance(auxModule).getContentEntries()) {
      if (!pluginDirs.contains(root.getFile())) {
        actions.add(removeStaleContentEntries(pluginDirs));
        break;
      }
    }

    if (!actions.isEmpty()) {
      actions.add(exportDefaultLibrary(structure.getUserLibraryName()));
    }

    if (!actions.isEmpty()) {
      final ModifiableRootModel model = ModuleRootManager.getInstance(auxModule).getModifiableModel();
      for (final Consumer<ModifiableRootModel> pluginsUpdateAction : actions) {
        pluginsUpdateAction.consume(model);
      }
      model.commit();
    }
  }

  public static Consumer<ModifiableRootModel> exportDefaultLibrary(final String libraryName) {
    return new Consumer<ModifiableRootModel>() {
      @Override
      public void consume(ModifiableRootModel modifiableRootModel) {
        for (final OrderEntry entry : modifiableRootModel.getOrderEntries()) {
          if (entry instanceof LibraryOrderEntry) {
            final LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)entry;
            String lName = libraryOrderEntry.getLibraryName();
            if (lName != null && lName.startsWith(libraryName)) {
              libraryOrderEntry.setExported(true);
            }
          }
        }
      }
    };
  }

  private static boolean hasChildDirectory(VirtualFile file) {
    for (VirtualFile virtualFile : file.getChildren()) {
      if (virtualFile.isDirectory()) return true;
    }

    return false;
  }

  public static void updateGlobalPluginModule(@NotNull Project project, @NotNull MvcFramework framework) {
    MultiMap<VirtualFile, Module> map = new MultiMap<VirtualFile, Module>();

    for (Module module : ModuleManager.getInstance(project).getModules()) {
      if (framework.hasSupport(module)) {
        VirtualFile globalPluginsDir = refreshAndFind(framework.getGlobalPluginsDir(module));
        if (globalPluginsDir != null && hasChildDirectory(globalPluginsDir)) {
          map.putValue(globalPluginsDir, module);
        }
      }
    }

    Map<VirtualFile, Module> globalAuxModules = new HashMap<VirtualFile, Module>();

    for (Module module : ModuleManager.getInstance(project).getModules()) {
      if (framework.isGlobalPluginModule(module)) {
        VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();

        VirtualFile parent = null;

        if (contentRoots.length > 0) {
          parent = contentRoots[0].getParent();
          if (!map.containsKey(parent)) {
            parent = null;
          }
          else {
            for (int i = 1; i < contentRoots.length; i++) {
              if (!Comparing.equal(parent, contentRoots[i].getParent())) {
                parent = null;
                break;
              }
            }
          }
        }

        if (parent == null) {
          removeAuxiliaryModule(module);
        }
        else {
          globalAuxModules.put(parent, module);
        }
      }
    }

    for (VirtualFile virtualFile : map.keySet()) {
      if (!globalAuxModules.containsKey(virtualFile)) {
        Module appModule = map.get(virtualFile).iterator().next();
        Module module =
          createAuxiliaryModule(appModule, generateUniqueModuleName(project, framework.getGlobalPluginsModuleName()), framework);
        globalAuxModules.put(virtualFile, module);
      }
    }

    assert map.size() == globalAuxModules.size();

    for (VirtualFile virtualFile : map.keySet()) {
      List<VirtualFile> pluginRoots = new ArrayList<VirtualFile>();

      for (VirtualFile child : virtualFile.getChildren()) {
        if (child.isDirectory()) {
          pluginRoots.add(child);
        }
      }

      assert !pluginRoots.isEmpty();

      Module auxModule = globalAuxModules.get(virtualFile);

      updateAuxModuleStructure(auxModule, pluginRoots, framework);

      for (Module appModule : map.get(virtualFile)) {
        ensureDependency(appModule, auxModule, false);

        Module commonPluginsModule = framework.findCommonPluginsModule(appModule);
        if (commonPluginsModule != null) {
          ensureDependency(commonPluginsModule, auxModule, false);
        }
      }
    }
  }

  private static String generateUniqueModuleName(@NotNull Project project, String prefix) {
    ModuleManager manager = ModuleManager.getInstance(project);
    int i = 0;
    do {
      String res = i == 0 ? prefix : prefix + i;
      i++;

      if (manager.findModuleByName(res) == null) return res;
    }
    while (true);
  }

  @Nullable
  public static Module updateAuxiliaryPluginsModuleRoots(Module appModule, MvcFramework framework) {
    Module commonPluginsModule = framework.findCommonPluginsModule(appModule);

    Set<VirtualFile> pluginRoots = new HashSet<VirtualFile>();

    VirtualFile globalPluginsDir = refreshAndFind(framework.getGlobalPluginsDir(appModule));

    for (VirtualFile pluginRoot : framework.getCommonPluginRoots(appModule, true)) {
      if (checkValidity(pluginRoot)) {
        if (globalPluginsDir == null || !VfsUtil.isAncestor(globalPluginsDir, pluginRoot, true)) {
          pluginRoots.add(pluginRoot);
        }
      }
    }

    if (pluginRoots.isEmpty()) {
      if (commonPluginsModule != null) {
        removeAuxiliaryModule(commonPluginsModule);
      }
      return null;
    }

    if (commonPluginsModule == null) {
      commonPluginsModule = createAuxiliaryModule(appModule, framework.getCommonPluginsModuleName(appModule), framework);
    }

    ensureDependency(appModule, commonPluginsModule, false);
    updateAuxModuleStructure(commonPluginsModule, pluginRoots, framework);

    return commonPluginsModule;
  }

  public static Library findUserLibrary(@NotNull Module module, @NotNull final String name) {
    CommonProcessors.FindProcessor<Library> processor = new CommonProcessors.FindProcessor<Library>() {
      @Override
      protected boolean accept(Library library) {
        String libraryName = library.getName();
        return libraryName != null && libraryName.startsWith(name);
      }
    };

    OrderEnumerator.orderEntries(module).forEachLibrary(processor);

    return processor.getFoundValue();
  }

  @Nullable
  public static VirtualFile refreshAndFind(@Nullable File file) {
    return findFile(file, true);
  }

  @Nullable
  public static VirtualFile findFile(@Nullable File file, boolean refresh) {
    if (file == null) return null;

    if (refresh) {
      ApplicationManager.getApplication().assertIsDispatchThread();
      return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
    }
    else {
      return LocalFileSystem.getInstance().findFileByIoFile(file);
    }
  }

  public static boolean isEnabledStructureUpdate() {
    return !Boolean.parseBoolean(System.getProperty("grails.disable.structure.update"));
  }
}
