// 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.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.buildeventservice.client.BuildEventServiceClient;
import com.google.devtools.build.lib.buildeventservice.client.BuildEventServiceGrpcClient;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
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;

  @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(),
              env.getCommandLinePathFactory(),
              env.getRuntime().getFileSystem(),
              newConfig.authAndTLSOptions());

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

  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 "";
  }
}
