/*
 * 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.plugin.run;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.idea.blaze.base.async.executor.BlazeExecutor;
import com.google.idea.blaze.base.command.buildresult.BuildResultHelper;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.repackaged.devtools.intellij.plugin.IntellijPluginTargetDeployInfo.IntellijPluginDeployFile;
import com.google.repackaged.devtools.intellij.plugin.IntellijPluginTargetDeployInfo.IntellijPluginDeployInfo;
import com.google.repackaged.protobuf.TextFormat;
import com.intellij.concurrency.AsyncUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.Key;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import javax.annotation.Nullable;

/** Handles finding files to deploy and copying these into the sandbox. */
class BlazeIntellijPluginDeployer {

  static final Key<BlazeIntellijPluginDeployer> USER_DATA_KEY =
      Key.create(BlazeIntellijPluginDeployer.class.getName());

  private final String sandboxHome;
  private final String buildNumber;
  private final Label pluginTarget;
  private final List<File> deployInfoFiles = new ArrayList<>();
  private final Map<File, File> filesToDeploy = Maps.newHashMap();
  private File executionRoot;

  private Future<Void> fileCopyingTask;

  BlazeIntellijPluginDeployer(String sandboxHome, String buildNumber, Label pluginTarget) {
    this.sandboxHome = sandboxHome;
    this.buildNumber = buildNumber;
    this.pluginTarget = pluginTarget;
  }

  void reportBuildComplete(File executionRoot, BuildResultHelper buildResultHelper) {
    this.executionRoot = executionRoot;
    for (File file : buildResultHelper.getBuildArtifactsForTarget(pluginTarget)) {
      if (file.getName().endsWith(".intellij-plugin-debug-target-deploy-info")) {
        deployInfoFiles.add(file);
      }
    }
  }

  /**
   * Returns a list of plugin IDs, and asynchronously copies the corresponding files to the sandbox.
   */
  List<String> deployNonBlocking() throws ExecutionException {
    List<IntellijPluginDeployInfo> deployInfoList = Lists.newArrayList();
    for (File deployInfoFile : deployInfoFiles) {
      deployInfoList.addAll(readDeployInfoFromFile(deployInfoFile));
    }
    ImmutableMap<File, File> filesToDeploy = getFilesToDeploy(executionRoot, deployInfoList);
    this.filesToDeploy.putAll(filesToDeploy);

    for (File file : filesToDeploy.keySet()) {
      if (!file.exists()) {
        throw new ExecutionException(
            String.format("Plugin file '%s' not found. Did the build fail?", file.getName()));
      }
    }
    // kick off file copying task asynchronously, so it doesn't block the EDT.
    fileCopyingTask =
        BlazeExecutor.getInstance()
            .submit(
                () -> {
                  for (Map.Entry<File, File> entry : filesToDeploy.entrySet()) {
                    copyFileToSandbox(entry.getKey(), entry.getValue());
                  }
                  return null;
                });

    return readPluginIds(filesToDeploy.keySet());
  }

  /** Blocks until the plugin files have been copied to the sandbox */
  void blockUntilDeployComplete() {
    AsyncUtil.get(fileCopyingTask);
    fileCopyingTask = null;
  }

  void deleteDeployment() {
    for (File file : filesToDeploy.values()) {
      if (file.exists()) {
        file.delete();
      }
    }
  }

  private static ImmutableList<IntellijPluginDeployInfo> readDeployInfoFromFile(File deployInfoFile)
      throws ExecutionException {
    ImmutableList.Builder<IntellijPluginDeployInfo> result = ImmutableList.builder();
    try (InputStream inputStream = new BufferedInputStream(new FileInputStream(deployInfoFile))) {
      IntellijPluginDeployInfo.Builder builder = IntellijPluginDeployInfo.newBuilder();
      TextFormat.Parser parser = TextFormat.Parser.newBuilder().setAllowUnknownFields(true).build();
      parser.merge(new InputStreamReader(inputStream, UTF_8), builder);
      IntellijPluginDeployInfo deployInfo = builder.build();
      result.add(deployInfo);
    } catch (IOException e) {
      throw new ExecutionException(e);
    }
    return result.build();
  }

  private ImmutableMap<File, File> getFilesToDeploy(
      File executionRoot, Collection<IntellijPluginDeployInfo> deployInfos) {
    ImmutableMap.Builder<File, File> result = ImmutableMap.builder();
    for (IntellijPluginDeployInfo deployInfo : deployInfos) {
      for (IntellijPluginDeployFile deployFile : deployInfo.getDeployFilesList()) {
        File src = new File(executionRoot, deployFile.getExecutionPath());
        File dest = new File(sandboxPluginDirectory(sandboxHome), deployFile.getDeployLocation());
        result.put(src, dest);
      }
    }
    return result.build();
  }

  private static File sandboxPluginDirectory(String sandboxHome) {
    return new File(sandboxHome, "plugins");
  }

  private List<String> readPluginIds(Collection<File> files) throws ExecutionException {
    List<String> pluginIds = Lists.newArrayList();
    for (File file : files) {
      if (file.getName().endsWith(".jar")) {
        String pluginId = readPluginIdFromJar(buildNumber, file);
        if (pluginId != null) {
          pluginIds.add(pluginId);
        }
      }
    }
    return pluginIds;
  }

  @Nullable
  private static String readPluginIdFromJar(String buildNumber, File jar)
      throws ExecutionException {
    IdeaPluginDescriptor pluginDescriptor = PluginManagerCore.loadDescriptor(jar, "plugin.xml");
    if (pluginDescriptor == null) {
      return null;
    }
    if (PluginManagerCore.isIncompatible(pluginDescriptor, BuildNumber.fromString(buildNumber))) {
      throw new ExecutionException(
          String.format(
              "Plugin SDK version '%s' is incompatible with this plugin "
                  + "(since: '%s', until: '%s')",
              buildNumber, pluginDescriptor.getSinceBuild(), pluginDescriptor.getUntilBuild()));
    }
    return pluginDescriptor.getPluginId().getIdString();
  }

  private static void copyFileToSandbox(File src, File dest) throws ExecutionException {
    try {
      dest.getParentFile().mkdirs();
      Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
      dest.deleteOnExit();
    } catch (IOException e) {
      throw new ExecutionException("Error copying plugin file to sandbox", e);
    }
  }
}
