// 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.devtools.build.lib.bazel.repository;

import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache;
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache.KeyType;
import com.google.devtools.build.lib.bazel.repository.downloader.HttpDownloader;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.rules.repository.WorkspaceAttributeMapper;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.Path;
import java.io.IOException;
import java.util.Map;
import java.util.StringJoiner;
import javax.annotation.Nullable;
import org.apache.maven.settings.Server;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.Authentication;
import org.eclipse.aether.repository.AuthenticationContext;
import org.eclipse.aether.repository.AuthenticationDigest;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;

/**
 * Downloader for JAR files from Maven repositories.
 * TODO(jingwen): standardize interface between this and HttpDownloader
 */
public class MavenDownloader extends HttpDownloader {

  public MavenDownloader(RepositoryCache repositoryCache) {
    super(repositoryCache);
  }

  /**
   * Download the Maven artifact to the output directory. Returns the path to the jar (and the
   * srcjar if available).
   */
  public JarPaths download(
      String name,
      WorkspaceAttributeMapper mapper,
      Path outputDirectory,
      MavenServerValue serverValue,
      ExtendedEventHandler eventHandler)
      throws IOException, EvalException, InterruptedException {

    String url = serverValue.getUrl();
    Server server = serverValue.getServer();

    // Initialize maven artifacts
    String artifactCoords = mapper.get("artifact", Type.STRING);
    String sha1 = retrieveSha1(name, "sha1", mapper);
    String sha1Src = retrieveSha1(name, "sha1_src", mapper);

    Artifact artifact;
    try {
      artifact = new DefaultArtifact(artifactCoords);
    } catch (IllegalArgumentException e) {
      throw new IOException(e.getMessage());
    }

    Artifact artifactWithSrcs = srcjarCoords(artifact);

    boolean isCaching = repositoryCache.isEnabled() && KeyType.SHA1.isValid(sha1);

    if (isCaching) {
      Path downloadPath = getDownloadDestination(outputDirectory, artifact);
      try {
        Path cachedDestination = repositoryCache.get(sha1, downloadPath, KeyType.SHA1);
        if (cachedDestination != null) {
          Path cachedDestinationSrc = null;
          if (sha1Src != null) {
            Path downloadPathSrc = getDownloadDestination(outputDirectory, artifactWithSrcs);
            cachedDestinationSrc = repositoryCache.get(sha1Src, downloadPathSrc, KeyType.SHA1);
          }
          return new JarPaths(cachedDestination, Optional.fromNullable(cachedDestinationSrc));
        }
      } catch (IOException e) {
        eventHandler.handle(
            Event.debug("RepositoryCache entry " + sha1 + " is invalid, replacing it..."));
        // Ignore error trying to get. We'll just download again.
      }
    }

    // Setup env for fetching jars
    MavenConnector connector = new MavenConnector(outputDirectory.getPathString());
    RepositorySystem system = connector.newRepositorySystem();
    RepositorySystemSession session = connector.newRepositorySystemSession(system);
    RemoteRepository repository =
        new RemoteRepository.Builder(name, MavenServerValue.DEFAULT_ID, url)
            .setAuthentication(new MavenAuthentication(server))
            .build();

    // Try fetching jar.
    final Path jarDownload;
    try {
      artifact = downloadArtifact(artifact, repository, session, system);
    } catch (ArtifactResolutionException e) {
      throw new IOException("Failed to fetch Maven dependency: " + e.getMessage());
    }

    // Try also fetching srcjar.
    try {
      artifactWithSrcs = downloadArtifact(artifactWithSrcs, repository, session, system);
    } catch (ArtifactResolutionException e) {
      // Intentionally ignored - missing srcjar is not an error.
    }

    jarDownload = outputDirectory.getRelative(artifact.getFile().getAbsolutePath());
    // Verify checksum.
    if (!Strings.isNullOrEmpty(sha1)) {
      RepositoryCache.assertFileChecksum(sha1, jarDownload, KeyType.SHA1);
    }

    Path srcjarDownload = null;
    if (artifactWithSrcs.getFile() != null) {
      srcjarDownload = outputDirectory.getRelative(artifactWithSrcs.getFile().getAbsolutePath());
      if (!Strings.isNullOrEmpty(sha1Src)) {
        RepositoryCache.assertFileChecksum(sha1Src, srcjarDownload, KeyType.SHA1);
      }
    }

    if (isCaching) {
      repositoryCache.put(sha1, jarDownload, KeyType.SHA1);
      if (srcjarDownload != null && !Strings.isNullOrEmpty(sha1Src)) {
        repositoryCache.put(sha1Src, srcjarDownload, KeyType.SHA1);
      }
    }

    return new JarPaths(jarDownload, Optional.fromNullable(srcjarDownload));
  }

  private String retrieveSha1(String name, String attribute, WorkspaceAttributeMapper mapper)
      throws EvalException, IOException {
    String sha1 =
        mapper.isAttributeValueExplicitlySpecified(attribute)
            ? mapper.get(attribute, Type.STRING)
            : null;
    if (sha1 != null && !KeyType.SHA1.isValid(sha1)) {
      throw new IOException("Invalid SHA-1 for maven_jar " + name + ": '" + sha1 + "'");
    }
    return sha1;
  }

  private Path getDownloadDestination(Path outputDirectory, Artifact artifact) {
    String groupIdPath = artifact.getGroupId().replace('.', '/');
    String artifactId = artifact.getArtifactId();
    String classifier = artifact.getClassifier();
    String version = artifact.getVersion();
    String filename = artifactId + '-' + version;

    if (classifier.equals("sources")) {
      filename += "-sources";
    }
    filename += '.' + artifact.getExtension();

    StringJoiner joiner = new StringJoiner("/");
    joiner.add(groupIdPath).add(artifactId).add(version).add(filename);

    return outputDirectory.getRelative(joiner.toString());
  }

  private Artifact srcjarCoords(Artifact jar) {
    return new DefaultArtifact(
        jar.getGroupId(), jar.getArtifactId(), "sources", jar.getExtension(), jar.getVersion());
  }

  /*
   * Set up request for and resolve (retrieve to local repo) artifact
   */
  private Artifact downloadArtifact(
      Artifact artifact,
      RemoteRepository repository,
      RepositorySystemSession session,
      RepositorySystem system)
      throws ArtifactResolutionException {
    ArtifactRequest artifactRequest = new ArtifactRequest();
    artifactRequest.setArtifact(artifact);
    artifactRequest.setRepositories(ImmutableList.of(repository));
    ArtifactResult artifactResult = system.resolveArtifact(session, artifactRequest);
    return artifactResult.getArtifact();
  }

  /*
   * Class for packaging srcjar and jar paths together when srcjar is available.
   */
  static class JarPaths {
    final Path jar;
    @Nullable final Optional<Path> srcjar;

    private JarPaths(Path jar, Optional<Path> srcjar) {
      this.jar = jar;
      this.srcjar = srcjar;
    }
  }

  private static class MavenAuthentication implements Authentication {

    private final Map<String, String> authenticationInfo;

    private MavenAuthentication(Server server) {
      ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String>builder();
      // From https://maven.apache.org/settings.html: "If you use a private key to login to the
      // server, make sure you omit the <password> element. Otherwise, the key will be ignored."
      if (server.getPassword() != null) {
        builder.put(AuthenticationContext.USERNAME, server.getUsername());
        builder.put(AuthenticationContext.PASSWORD, server.getPassword());
      } else if (server.getPrivateKey() != null) {
        // getPrivateKey sounds like it returns the key, but it actually returns a path to it.
        builder.put(AuthenticationContext.PRIVATE_KEY_PATH, server.getPrivateKey());
        builder.put(AuthenticationContext.PRIVATE_KEY_PASSPHRASE, server.getPassphrase());
      }
      authenticationInfo = builder.build();
    }

    @Override
    public void fill(
        AuthenticationContext authenticationContext, String s, Map<String, String> map) {
      for (Map.Entry<String, String> entry : authenticationInfo.entrySet()) {
        authenticationContext.put(entry.getKey(), entry.getValue());
      }
    }

    @Override
    public void digest(AuthenticationDigest authenticationDigest) {
      // No-op.
    }
  }
}
