/*
 * Copyright 2000-2010 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.intellij.ide.projectView.actions;

import com.intellij.ide.projectView.impl.ProjectRootsUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.DirectoryIndex;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * @author yole
 */
public abstract class MarkRootActionBase extends DumbAwareAction {
  @Override
  public void actionPerformed(AnActionEvent e) {
    VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
    final Module module = getModule(e, files);
    if (module == null) {
      return;
    }

    final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
    for (VirtualFile file : files) {
      ContentEntry entry = findContentEntry(model, file);
      if (entry != null) {
        final SourceFolder[] sourceFolders = entry.getSourceFolders();
        for (SourceFolder sourceFolder : sourceFolders) {
          if (Comparing.equal(sourceFolder.getFile(), file)) {
            entry.removeSourceFolder(sourceFolder);
            break;
          }
        }
        modifyRoots(file, entry);
      }
    }
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        model.commit();
        module.getProject().save();
      }
    });
  }

  protected abstract void modifyRoots(VirtualFile file, ContentEntry entry);

  @Nullable
  public static ContentEntry findContentEntry(@NotNull ModuleRootModel model, @NotNull VirtualFile vFile) {
    final ContentEntry[] contentEntries = model.getContentEntries();
    for (ContentEntry contentEntry : contentEntries) {
      final VirtualFile contentEntryFile = contentEntry.getFile();
      if (contentEntryFile != null && VfsUtilCore.isAncestor(contentEntryFile, vFile, false)) {
        return contentEntry;
      }
    }
    return null;
  }

  @Override
  public void update(AnActionEvent e) {
    RootsSelection selection = getSelection(e);
    doUpdate(e, e.getData(LangDataKeys.MODULE), selection);
  }

  protected void doUpdate(@NotNull AnActionEvent e, @Nullable Module module, @NotNull RootsSelection selection) {
    boolean enabled = module != null && (!selection.mySelectedRoots.isEmpty() || !selection.mySelectedDirectories.isEmpty())
                      && selection.mySelectedExcludeRoots.isEmpty() && isEnabled(selection, module);
    e.getPresentation().setEnabledAndVisible(enabled);
  }

  protected abstract boolean isEnabled(@NotNull RootsSelection selection, @NotNull Module module);

  protected static RootsSelection getSelection(AnActionEvent e) {
    VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
    Module module = getModule(e, files);
    if (module == null) return RootsSelection.EMPTY;

    RootsSelection selection = new RootsSelection();
    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex();
    for (VirtualFile file : files) {
      if (!file.isDirectory()) {
        return RootsSelection.EMPTY;
      }
      if (!fileIndex.isInContent(file)) {
        ExcludeFolder excludeFolder = ProjectRootsUtil.findExcludeFolder(module, file);
        if (excludeFolder != null) {
          selection.mySelectedExcludeRoots.add(excludeFolder);
          continue;
        }
        else {
          return RootsSelection.EMPTY;
        }
      }
      SourceFolder folder;
      if (Comparing.equal(fileIndex.getSourceRootForFile(file), file) && ((folder = ProjectRootsUtil.findSourceFolder(module, file)) != null)) {
        selection.mySelectedRoots.add(folder);
      }
      else {
        selection.mySelectedDirectories.add(file);
        if (fileIndex.isInSourceContent(file)) {
          selection.myHaveSelectedFilesUnderSourceRoots = true;
        }
      }
    }
    return selection;
  }

  @Nullable
  private static Module getModule(@NotNull AnActionEvent e, @Nullable VirtualFile[] files) {
    if (files == null) return null;
    Module module = e.getData(LangDataKeys.MODULE);
    if (module == null) {
      module = findParentModule(e.getProject(), files);
    }
    return module;
  }

  @Nullable
  private static Module findParentModule(@Nullable Project project, @NotNull VirtualFile[] files) {
    if (project == null) return null;
    Module result = null;
    DirectoryIndex index = DirectoryIndex.getInstance(project);
    for (VirtualFile file : files) {
      Module module = index.getInfoForFile(file).getModule();
      if (module == null) return null;
      if (result == null) {
        result = module;
      }
      else if (!result.equals(module)) {
        return null;
      }
    }
    return result;
  }

  protected static class RootsSelection {
    public static final RootsSelection EMPTY = new RootsSelection();

    public List<SourceFolder> mySelectedRoots = new ArrayList<SourceFolder>();
    public List<ExcludeFolder> mySelectedExcludeRoots = new ArrayList<ExcludeFolder>();
    public List<VirtualFile> mySelectedDirectories = new ArrayList<VirtualFile>();
    public boolean myHaveSelectedFilesUnderSourceRoots;
  }
}
