// Copyright 2017 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.buildeventservice;

import com.google.auth.Credentials;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions;
import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperEnvironment;
import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialModule;
import com.google.devtools.build.lib.buildeventservice.client.BuildEventServiceClient;
import com.google.devtools.build.lib.buildeventservice.client.BuildEventServiceGrpcClient;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.WorkspaceBuilder;
import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannel;
import io.grpc.Metadata;
import io.grpc.auth.MoreCallCredentials;
import io.grpc.stub.MetadataUtils;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;

/** Bazel's BES module. */
public class BazelBuildEventServiceModule
    extends BuildEventServiceModule<BuildEventServiceOptions> {

  @AutoValue
  abstract static class BackendConfig {
    abstract String besBackend();

    @Nullable
    abstract String besProxy();

    abstract ImmutableList<Map.Entry<String, String>> besHeaders();

    abstract AuthAndTLSOptions authAndTLSOptions();

    static BackendConfig create(
        BuildEventServiceOptions besOptions, AuthAndTLSOptions authAndTLSOptions) {
      return new AutoValue_BazelBuildEventServiceModule_BackendConfig(
          besOptions.besBackend,
          besOptions.besProxy,
          ImmutableMap.copyOf(besOptions.besHeaders).entrySet().asList(),
          authAndTLSOptions);
    }
  }

  private BuildEventServiceClient client;
  private BackendConfig config;

  private CredentialModule credentialModule;

  @Override
  public void workspaceInit(
      BlazeRuntime runtime, BlazeDirectories directories, WorkspaceBuilder builder) {
    Preconditions.checkState(credentialModule == null, "credentialModule must be null");
    credentialModule = Preconditions.checkNotNull(runtime.getBlazeModule(CredentialModule.class));
  }

  @Override
  protected Class<BuildEventServiceOptions> optionsClass() {
    return BuildEventServiceOptions.class;
  }

  @Override
  protected BuildEventServiceClient getBesClient(
      CommandEnvironment env,
      BuildEventServiceOptions besOptions,
      AuthAndTLSOptions authAndTLSOptions)
      throws IOException {
    BackendConfig newConfig = BackendConfig.create(besOptions, authAndTLSOptions);
    if (client == null || !Objects.equals(config, newConfig)) {
      clearBesClient();
      Preconditions.checkState(config == null);
      Preconditions.checkState(client == null);

      Credentials credentials =
          GoogleAuthUtils.newCredentials(
              CredentialHelperEnvironment.newBuilder()
                  .setEventReporter(env.getReporter())
                  .setWorkspacePath(env.getWorkspace())
                  .setClientEnvironment(env.getClientEnv())
                  .setHelperExecutionTimeout(authAndTLSOptions.credentialHelperTimeout)
                  .build(),
              credentialModule.getCredentialCache(),
              env.getCommandLinePathFactory(),
              env.getRuntime().getFileSystem(),
              newConfig.authAndTLSOptions());

      config = newConfig;
      client =
          new BuildEventServiceGrpcClient(
              newGrpcChannel(config),
              credentials != null ? MoreCallCredentials.from(credentials) : null,
              makeGrpcInterceptor(config),
              env.getBuildRequestId(),
              env.getCommandId());
    }
    return client;
  }

  @Nullable
  private static ClientInterceptor makeGrpcInterceptor(BackendConfig config) {
    if (config.besHeaders().isEmpty()) {
      return null;
    }
    return MetadataUtils.newAttachHeadersInterceptor(makeGrpcMetadata(config));
  }

  @VisibleForTesting
  static Metadata makeGrpcMetadata(BackendConfig config) {
    Metadata extraHeaders = new Metadata();
    for (Entry<String, String> header : config.besHeaders()) {
      extraHeaders.put(
          Metadata.Key.of(header.getKey(), Metadata.ASCII_STRING_MARSHALLER), header.getValue());
    }
    return extraHeaders;
  }

  // newGrpcChannel is only defined so it can be overridden in tests to not use a real network link.
  @VisibleForTesting
  protected ManagedChannel newGrpcChannel(BackendConfig config) throws IOException {
    return GoogleAuthUtils.newChannel(
        /*executor=*/ null,
        config.besBackend(),
        config.besProxy(),
        config.authAndTLSOptions(),
        /* interceptors= */ null);
  }

  @Override
  protected void clearBesClient() {
    if (client != null) {
      client.shutdown();
    }
    this.client = null;
    this.config = null;
  }

  private static final ImmutableSet<String> ALLOWED_COMMANDS =
      ImmutableSet.of(
          "fetch",
          "build",
          "test",
          "run",
          "query",
          "aquery",
          "cquery",
          "coverage",
          "mobile-install");

  @Override
  protected Set<String> allowedCommands(BuildEventServiceOptions besOptions) {
    return ALLOWED_COMMANDS;
  }

  @Override
  protected String getInvocationIdPrefix() {
    if (Strings.isNullOrEmpty(besOptions.besResultsUrl)) {
      return "";
    }
    return besOptions.besResultsUrl.endsWith("/")
        ? besOptions.besResultsUrl
        : besOptions.besResultsUrl + "/";
  }

  @Override
  protected String getBuildRequestIdPrefix() {
    return "";
  }
}
