/*
 * 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.wizard2.ui;

import com.google.common.collect.Lists;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
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.ProjectView;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.ProjectViewSet.ProjectViewFile;
import com.google.idea.blaze.base.projectview.ProjectViewStorageManager;
import com.google.idea.blaze.base.projectview.ProjectViewVerifier;
import com.google.idea.blaze.base.projectview.parser.ProjectViewParser;
import com.google.idea.blaze.base.projectview.section.ScalarSection;
import com.google.idea.blaze.base.projectview.section.SectionParser;
import com.google.idea.blaze.base.projectview.section.sections.ImportSection;
import com.google.idea.blaze.base.projectview.section.sections.Sections;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.OutputSink.Propagation;
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.google.idea.blaze.base.scope.output.IssueOutput.Category;
import com.google.idea.blaze.base.settings.ui.JPanelProvidingProject;
import com.google.idea.blaze.base.settings.ui.ProjectViewUi;
import com.google.idea.blaze.base.sync.BlazeSyncPlugin;
import com.google.idea.blaze.base.sync.projectview.LanguageSupport;
import com.google.idea.blaze.base.sync.projectview.WorkspaceLanguageSettings;
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver;
import com.google.idea.blaze.base.ui.BlazeValidationError;
import com.google.idea.blaze.base.ui.BlazeValidationResult;
import com.google.idea.blaze.base.ui.UiUtil;
import com.google.idea.blaze.base.wizard2.BlazeNewProjectBuilder;
import com.google.idea.blaze.base.wizard2.BlazeSelectProjectViewOption;
import com.google.idea.blaze.base.wizard2.BlazeSelectWorkspaceOption;
import com.google.idea.blaze.base.wizard2.ProjectDataDirectoryValidator;
import com.google.idea.common.experiments.BoolExperiment;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.SystemProperties;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/** The UI control to collect project settings when importing a Blaze project. */
public final class BlazeEditProjectViewControl {

  private static final FileChooserDescriptor PROJECT_FOLDER_DESCRIPTOR =
      new FileChooserDescriptor(false, true, false, false, false, false);
  private static final Logger LOG = Logger.getInstance(BlazeEditProjectViewControl.class);

  private static final BoolExperiment allowAddprojectViewDefaultValues =
      new BoolExperiment("allow.add.project.view.default.values", true);

  private final JPanel component;
  private final String buildSystemName;
  private final ProjectViewUi projectViewUi;

  private TextFieldWithBrowseButton projectDataDirField;
  private JTextField projectNameField;
  private HashCode paramsHash;
  private WorkspaceRoot workspaceRoot;

  public BlazeEditProjectViewControl(BlazeNewProjectBuilder builder, Disposable parentDisposable) {
    this.projectViewUi = new ProjectViewUi(parentDisposable);
    JPanel component = new JPanelProvidingProject(ProjectViewUi.getProject(), new GridBagLayout());
    fillUi(component, 0);
    update(builder);
    UiUtil.fillBottom(component);
    this.component = component;
    this.buildSystemName = builder.getBuildSystemName();
  }

  public Component getUiComponent() {
    return component;
  }

  private void fillUi(JPanel canvas, int indentLevel) {
    JLabel projectDataDirLabel = new JBLabel("Project data directory:");

    Dimension minSize = ProjectViewUi.getMinimumSize();
    // Add 120 pixels so we have room for our extra fields
    minSize.setSize(minSize.width, minSize.height + 120);
    canvas.setMinimumSize(minSize);
    canvas.setPreferredSize(minSize);

    projectDataDirField = new TextFieldWithBrowseButton();
    projectDataDirField.addBrowseFolderListener(
        "",
        buildSystemName + " project data directory",
        null,
        PROJECT_FOLDER_DESCRIPTOR,
        TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT,
        false);
    final String dataDirToolTipText =
        "Directory in which to store the project's metadata. "
            + "Choose a directory outside of your workspace.";
    projectDataDirField.setToolTipText(dataDirToolTipText);
    projectDataDirLabel.setToolTipText(dataDirToolTipText);

    canvas.add(projectDataDirLabel, UiUtil.getLabelConstraints(indentLevel));
    canvas.add(projectDataDirField, UiUtil.getFillLineConstraints(0));

    JLabel projectNameLabel = new JLabel("Project name:");
    projectNameField = new JTextField();
    final String projectNameToolTipText = "Project display name.";
    projectNameField.setToolTipText(projectNameToolTipText);
    projectNameLabel.setToolTipText(projectNameToolTipText);
    canvas.add(projectNameLabel, UiUtil.getLabelConstraints(indentLevel));
    canvas.add(projectNameField, UiUtil.getFillLineConstraints(0));

    projectViewUi.fillUi(canvas, indentLevel);
  }

  public void update(BlazeNewProjectBuilder builder) {
    BlazeSelectWorkspaceOption workspaceOption = builder.getWorkspaceOption();
    BlazeSelectProjectViewOption projectViewOption = builder.getProjectViewOption();
    String workspaceName = workspaceOption.getWorkspaceName();
    WorkspaceRoot workspaceRoot = workspaceOption.getWorkspaceRoot();
    WorkspacePath workspacePath = projectViewOption.getSharedProjectView();
    String initialProjectViewText = projectViewOption.getInitialProjectViewText();
    boolean allowAddDefaultValues =
        projectViewOption.allowAddDefaultProjectViewValues()
            && allowAddprojectViewDefaultValues.getValue();
    WorkspacePathResolver workspacePathResolver = workspaceOption.getWorkspacePathResolver();

    HashCode hashCode =
        Hashing.md5()
            .newHasher()
            .putUnencodedChars(workspaceName)
            .putUnencodedChars(workspaceRoot.toString())
            .putUnencodedChars(workspacePath != null ? workspacePath.toString() : "")
            .putUnencodedChars(initialProjectViewText != null ? initialProjectViewText : "")
            .putBoolean(allowAddDefaultValues)
            .hash();

    // If any params have changed, reinit the control
    if (!hashCode.equals(paramsHash)) {
      this.paramsHash = hashCode;
      init(
          workspaceName,
          workspaceRoot,
          workspacePathResolver,
          workspacePath,
          initialProjectViewText,
          allowAddDefaultValues);
    }
  }

  private static String modifyInitialProjectView(
      String initialProjectViewText, WorkspacePathResolver workspacePathResolver) {
    BlazeContext context = new BlazeContext();
    ProjectViewParser projectViewParser = new ProjectViewParser(context, workspacePathResolver);
    projectViewParser.parseProjectView(initialProjectViewText);
    ProjectViewSet projectViewSet = projectViewParser.getResult();
    ProjectViewFile projectViewFile = projectViewSet.getTopLevelProjectViewFile();
    if (projectViewFile == null) {
      return initialProjectViewText;
    }
    ProjectView projectView = projectViewFile.projectView;
    for (SectionParser sectionParser : Sections.getParsers()) {
      projectView = sectionParser.addProjectViewDefaultValue(projectView);
    }
    return ProjectViewParser.projectViewToString(projectView);
  }

  private void init(
      String workspaceName,
      WorkspaceRoot workspaceRoot,
      WorkspacePathResolver workspacePathResolver,
      @Nullable WorkspacePath sharedProjectView,
      @Nullable String initialProjectViewText,
      boolean allowAddDefaultValues) {
    if (allowAddDefaultValues && initialProjectViewText != null) {
      initialProjectViewText =
          modifyInitialProjectView(initialProjectViewText, workspacePathResolver);
    }

    this.workspaceRoot = workspaceRoot;
    projectNameField.setText(workspaceName);
    String defaultDataDir = getDefaultProjectDataDirectory(workspaceName);
    projectDataDirField.setText(defaultDataDir);

    String projectViewText = "";
    File sharedProjectViewFile = null;

    if (sharedProjectView != null) {
      sharedProjectViewFile = workspacePathResolver.resolveToFile(sharedProjectView);

      try {
        projectViewText =
            ProjectViewStorageManager.getInstance().loadProjectView(sharedProjectViewFile);
        if (projectViewText == null) {
          LOG.error("Could not load project view: " + sharedProjectViewFile);
          projectViewText = "";
        }
      } catch (IOException e) {
        LOG.error(e);
      }
    } else {
      projectViewText = initialProjectViewText;
      LOG.assertTrue(projectViewText != null);
    }

    projectViewUi.init(
        workspacePathResolver,
        projectViewText,
        sharedProjectView != null ? projectViewText : null,
        sharedProjectView,
        sharedProjectView != null,
        false /* allowEditShared - not allowed during import */);
  }

  private static String getDefaultProjectDataDirectory(String projectName) {
    File defaultDataDirectory = new File(getDefaultProjectsDirectory());
    File desiredLocation = new File(defaultDataDirectory, projectName);
    return newUniquePath(desiredLocation);
  }

  private static String getDefaultProjectsDirectory() {
    final String lastProjectLocation =
        RecentProjectsManager.getInstance().getLastProjectCreationLocation();
    if (lastProjectLocation != null) {
      return lastProjectLocation.replace('/', File.separatorChar);
    }
    final String userHome = SystemProperties.getUserHome();
    String productName = ApplicationNamesInfo.getInstance().getLowercaseProductName();
    return userHome.replace('/', File.separatorChar)
        + File.separator
        + productName.replace(" ", "")
        + "Projects";
  }

  /** Returns a unique file path by appending numbers until a non-collision is found. */
  private static String newUniquePath(File location) {
    if (!location.exists()) {
      return location.getAbsolutePath();
    }

    String name = location.getName();
    File directory = location.getParentFile();
    int tries = 0;
    while (true) {
      String candidateName = String.format("%s-%02d", name, tries);
      File candidateFile = new File(directory, candidateName);
      if (!candidateFile.exists()) {
        return candidateFile.getAbsolutePath();
      }
      tries++;
    }
  }

  public BlazeValidationResult validate() {
    // Validate project settings fields
    String projectName = projectNameField.getText().trim();
    if (StringUtil.isEmpty(projectName)) {
      return BlazeValidationResult.failure(
          new BlazeValidationError("Project name is not specified"));
    }
    String projectDataDirPath = projectDataDirField.getText().trim();
    if (StringUtil.isEmpty(projectDataDirPath)) {
      return BlazeValidationResult.failure(
          new BlazeValidationError("Project data directory is not specified"));
    }
    File projectDataDir = new File(projectDataDirPath);
    if (!projectDataDir.isAbsolute()) {
      return BlazeValidationResult.failure(
          new BlazeValidationError("Project data directory is not valid"));
    }
    for (ProjectDataDirectoryValidator validator :
        ProjectDataDirectoryValidator.EP_NAME.getExtensions()) {
      BlazeValidationResult result = validator.validateDataDirectory(projectDataDir);
      if (!result.success) {
        return result;
      }
    }
    File workspaceRootDirectory = workspaceRoot.directory();
    if (FileUtil.isAncestor(projectDataDir, workspaceRootDirectory, false)) {
      return BlazeValidationResult.failure(
          new BlazeValidationError(
              "Project data directory must not contain the workspace. "
                  + "Please choose a directory outside your workspace."));
    }
    if (FileUtil.isAncestor(workspaceRootDirectory, projectDataDir, false)) {
      return BlazeValidationResult.failure(
          new BlazeValidationError(
              "Project data directory cannot be inside your workspace. "
                  + "Please choose a directory outside your workspace."));
    }

    List<IssueOutput> issues = Lists.newArrayList();

    ProjectViewSet projectViewSet = projectViewUi.parseProjectView(issues);
    BlazeValidationError projectViewParseError = validationErrorFromIssueList(issues);
    if (projectViewParseError != null) {
      return BlazeValidationResult.failure(projectViewParseError);
    }

    ProjectViewValidator projectViewValidator = new ProjectViewValidator(projectViewSet);
    ProgressManager.getInstance()
        .runProcessWithProgressSynchronously(
            projectViewValidator, "Validating Project", false, null);

    if (!projectViewValidator.success) {
      if (!projectViewValidator.errors.isEmpty()) {
        return BlazeValidationResult.failure(
            validationErrorFromIssueList(projectViewValidator.errors));
      }
      return BlazeValidationResult.failure(
          "Project view validation failed, but we couldn't find an error message. "
              + "Please report a bug.");
    }

    return BlazeValidationResult.success();
  }

  private static class ProjectViewValidator implements Runnable {
    private final ProjectViewSet projectViewSet;

    private boolean success;
    List<IssueOutput> errors = Lists.newArrayList();

    ProjectViewValidator(ProjectViewSet projectViewSet) {
      this.projectViewSet = projectViewSet;
    }

    @Override
    public void run() {
      success = Scope.root(this::validateProjectView);
    }

    @NotNull
    private Boolean validateProjectView(BlazeContext context) {
      context.addOutputSink(
          IssueOutput.class,
          output -> {
            if (output.getCategory() == Category.ERROR) {
              errors.add(output);
            }
            return Propagation.Continue;
          });
      for (BlazeSyncPlugin syncPlugin : BlazeSyncPlugin.EP_NAME.getExtensions()) {
        syncPlugin.installSdks(context);
      }
      WorkspaceLanguageSettings workspaceLanguageSettings =
          LanguageSupport.createWorkspaceLanguageSettings(context, projectViewSet);
      if (workspaceLanguageSettings == null) {
        return false;
      }
      return ProjectViewVerifier.verifyProjectViewNoDisk(
          context, projectViewSet, workspaceLanguageSettings);
    }
  }

  @Nullable
  private static BlazeValidationError validationErrorFromIssueList(List<IssueOutput> issues) {
    List<IssueOutput> errors =
        issues
            .stream()
            .filter(issue -> issue.getCategory() == IssueOutput.Category.ERROR)
            .collect(Collectors.toList());

    if (!errors.isEmpty()) {
      StringBuilder errorMessage = new StringBuilder();
      errorMessage.append("The following issues were found:\n\n");
      for (IssueOutput issue : errors) {
        errorMessage.append(issue.getMessage());
        errorMessage.append('\n');
      }
      return new BlazeValidationError(errorMessage.toString());
    }
    return null;
  }

  public void updateBuilder(BlazeNewProjectBuilder builder) {
    String projectName = projectNameField.getText().trim();
    String projectDataDirectory = projectDataDirField.getText().trim();
    File localProjectViewFile =
        ProjectViewStorageManager.getLocalProjectViewFileName(
            builder.getBuildSystem(), new File(projectDataDirectory));

    BlazeSelectProjectViewOption selectProjectViewOption = builder.getProjectViewOption();
    boolean useSharedProjectView = projectViewUi.getUseSharedProjectView();

    // If we're using a shared project view, synthesize a local one that imports the shared one
    ProjectViewSet parseResult = projectViewUi.parseProjectView(Lists.newArrayList());

    final ProjectView projectView;
    final ProjectViewSet projectViewSet;
    if (useSharedProjectView && selectProjectViewOption.getSharedProjectView() != null) {
      projectView =
          ProjectView.builder()
              .add(
                  ScalarSection.builder(ImportSection.KEY)
                      .set(selectProjectViewOption.getSharedProjectView()))
              .build();
      projectViewSet =
          ProjectViewSet.builder()
              .addAll(parseResult.getProjectViewFiles())
              .add(localProjectViewFile, projectView)
              .build();
    } else {
      ProjectViewSet.ProjectViewFile projectViewFile = parseResult.getTopLevelProjectViewFile();
      assert projectViewFile != null;
      projectView = projectViewFile.projectView;
      projectViewSet = parseResult;
    }

    builder
        .setProjectView(projectView)
        .setProjectViewFile(localProjectViewFile)
        .setProjectViewSet(projectViewSet)
        .setProjectName(projectName)
        .setProjectDataDirectory(projectDataDirectory);
  }
}
