/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.base.ide;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.idea.blaze.base.actions.BlazeAction;
import com.google.idea.blaze.base.buildmodifier.BuildFileModifier;
import com.google.idea.blaze.base.buildmodifier.FileSystemModifier;
import com.google.idea.blaze.base.metrics.Action;
import com.google.idea.blaze.base.model.primitives.Kind;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectViewManager;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.ScopedOperation;
import com.google.idea.blaze.base.scope.output.PrintOutput;
import com.google.idea.blaze.base.scope.output.StatusOutput;
import com.google.idea.blaze.base.scope.scopes.LoggedTimingScope;
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.sync.projectview.ImportRoots;
import com.intellij.history.LocalHistory;
import com.intellij.history.LocalHistoryAction;
import com.intellij.ide.IdeView;
import com.intellij.ide.util.DirectoryChooserUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;

public class NewBlazePackageAction extends BlazeAction implements DumbAware {
  private static final Logger LOG = Logger.getInstance(NewBlazePackageAction.class);

  private static final String BUILD_FILE_NAME = "BUILD";

  public NewBlazePackageAction() {
    super();
  }

  @Override
  public void actionPerformed(AnActionEvent event) {
    final IdeView view = event.getData(LangDataKeys.IDE_VIEW);
    final Project project = event.getData(CommonDataKeys.PROJECT);
    Scope.root(new ScopedOperation() {
      @Override
      public void execute(@NotNull final BlazeContext context) {
        context.push(new LoggedTimingScope(project, Action.CREATE_BLAZE_PACKAGE));

        if (view == null || project == null) {
          return;
        }
        PsiDirectory directory = getOrChooseDirectory(project, view);

        if (directory == null) {
          return;
        }

        NewBlazePackageDialog newBlazePackageDialog = new NewBlazePackageDialog(project, directory);
        boolean isOk = newBlazePackageDialog.showAndGet();
        if (!isOk) {
          return;
        }

        final Label newRule = newBlazePackageDialog.getNewRule();
        final Kind newRuleKind = newBlazePackageDialog.getNewRuleKind();
        // If we returned OK, we should have a non null result
        LOG.assertTrue(newRule != null);
        LOG.assertTrue(newRuleKind != null);

        context.output(new StatusOutput(String.format("Setting up a new %s package", Blaze.buildSystemName(project))));

        boolean success = createPackageOnDisk(
          project,
          context,
          newRule,
          newRuleKind
        );

        if (!success) {
          return;
        }

        File newDirectory = WorkspaceRoot.fromProject(project).fileForPath(newRule.blazePackage());
        VirtualFile virtualFile = VfsUtil.findFileByIoFile(newDirectory, true);
        // We just created this file, it should exist
        LOG.assertTrue(virtualFile != null);
        PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
        view.selectElement(psiFile);
      }
    });
  }

  private static Boolean createPackageOnDisk(
    @NotNull Project project,
    @NotNull BlazeContext context,
    @NotNull Label newRule,
    @NotNull Kind ruleKind) {
    LocalHistoryAction action;

    String actionName = String.format("Creating %s package: %s", Blaze.buildSystemName(project), newRule.toString());
    LocalHistory localHistory = LocalHistory.getInstance();
    action = localHistory.startAction(actionName);

    // Create the package + BUILD file + rule
    FileSystemModifier fileSystemModifier = FileSystemModifier.getInstance(project);
    WorkspacePath newWorkspacePath = newRule.blazePackage();
    File newDirectory = fileSystemModifier.makeWorkspacePathDirs(newWorkspacePath);
    if (newDirectory == null) {
      String errorMessage = "Could not create new package directory: " + newWorkspacePath.toString();
      context.output(PrintOutput.error(errorMessage));
      return false;
    }
    File buildFile = fileSystemModifier.createFile(newWorkspacePath, BUILD_FILE_NAME);
    if (buildFile == null) {
      String errorMessage =
        "Could not create new BUILD file in package: " + newWorkspacePath.toString();
      context.output(PrintOutput.error(errorMessage));
      return false;
    }
    BuildFileModifier buildFileModifier = BuildFileModifier.getInstance();
    buildFileModifier.addRule(project, context, newRule, ruleKind);
    action.finish();

    return true;
  }

  @Override
  protected void doUpdate(@NotNull AnActionEvent event) {
    Presentation presentation = event.getPresentation();
    if (isEnabled(event)) {
      String text = String.format("New %s Package", Blaze.buildSystemName(event.getProject()));
      presentation.setEnabledAndVisible(true);
      presentation.setText(text);
      presentation.setDescription(text);
      presentation.setIcon(PlatformIcons.PACKAGE_ICON);
    } else {
      presentation.setEnabledAndVisible(false);
    }
  }

  private boolean isEnabled(AnActionEvent event) {
    Project project = event.getProject();
    IdeView view = event.getData(LangDataKeys.IDE_VIEW);
    if (project == null || view == null) {
      return false;
    }

    List<PsiDirectory> directories = filterDirectories(project, view.getDirectories());
    if (directories.isEmpty()) {
      return false;
    }

    return true;
  }

  /**
   * Filter out directories that do not live under the project's directories.
   */
  private static List<PsiDirectory> filterDirectories(Project project, PsiDirectory[] directories) {
    if (directories.length == 0) {
      return ImmutableList.of();
    }
    ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
    if (projectViewSet == null) {
      return ImmutableList.of();
    }
    WorkspaceRoot workspaceRoot = WorkspaceRoot.fromProject(project);
    ImportRoots importRoots = ImportRoots.builder(workspaceRoot, Blaze.getBuildSystem(project)).add(projectViewSet).build();
    return Lists.newArrayList(directories).stream()
      .filter(directory -> isUnderProjectViewDirectory(workspaceRoot, importRoots, directory))
      .collect(Collectors.toList());
  }

  private static boolean isUnderProjectViewDirectory(WorkspaceRoot workspaceRoot,
                                                     ImportRoots importRoots,
                                                     PsiDirectory directory) {
    VirtualFile virtualFile = directory.getVirtualFile();
    // Ignore jars, etc. and their contents, which are in an ArchiveFileSystem.
    if (!(virtualFile.isInLocalFileSystem())) {
      return false;
    }
    if (!workspaceRoot.isInWorkspace(virtualFile)) {
      return false;
    }
    WorkspacePath workspacePath = workspaceRoot.workspacePathFor(virtualFile);
    return importRoots.rootDirectories().stream()
      .anyMatch(importRoot -> FileUtil.isAncestor(importRoot.relativePath(), workspacePath.relativePath(), false));
  }

  @Nullable
  private static PsiDirectory getOrChooseDirectory(Project project, IdeView view) {
    List<PsiDirectory> dirs = filterDirectories(project, view.getDirectories());
    if (dirs.size() == 0) {
      return null;
    }
    if (dirs.size() == 1) {
      return dirs.get(0);
    }
    else {
      return DirectoryChooserUtil.selectDirectory(project, dirs.toArray(new PsiDirectory[dirs.size()]), null, "");
    }
  }
}
