// Copyright 2018 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.exec;

import com.google.auto.value.AutoValue;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.MutableClassToInstanceMap;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.ActionContext;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.ExecutionOptions.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * Registry containing all available {@linkplain ActionContext action contexts}.
 *
 * <p>Contexts can be {@linkplain #getContext queried} by a common subtype of {@link ActionContext}
 * that they implement (which can be the implementation class itself). It is possible to {@linkplain
 * Builder#restrictTo restrict) the available contexts for a type to those who were {@linkplain
 * Builder#register registered with specific command-line identifiers}. If more than one context was
 * {@link Builder#register registered} for the same type and they are not distinguished by the
 * restriction then this registry will return the last registered context.
 *
 * <p>An instance of this registry can be created using its {@linkplain Builder builder}, which is
 * available to Blaze modules during server startup.
 */
public final class ModuleActionContextRegistry
    implements ActionContext, ActionContext.ActionContextRegistry {

  private final ImmutableClassToInstanceMap<ActionContext> identifyingTypeToContext;

  private ModuleActionContextRegistry(
      ImmutableClassToInstanceMap<ActionContext> identifyingTypeToContext) {
    this.identifyingTypeToContext = identifyingTypeToContext;
  }

  @Override
  public <T extends ActionContext> T getContext(Class<T> identifyingType) {
    return identifyingTypeToContext.getInstance(identifyingType);
  }

  /**
   * Notifies all contexts stored in this registry that they are {@linkplain
   * ActionContext#usedContext used}.
   */
  public void notifyUsed() {
    for (ActionContext context : identifyingTypeToContext.values()) {
      context.usedContext(this);
    }
  }

  /**
   * Records the list of all contexts that can be {@linkplain #getContext returned by this registry}
   * to the given reporter.
   */
  void writeActionContextsTo(Reporter reporter) {
    for (Map.Entry<Class<? extends ActionContext>, ActionContext> typeToContext :
        identifyingTypeToContext.entrySet()) {
      reporter.handle(
          Event.info(
              String.format(
                  "IdentifyingTypeToContext: \"%s\" = [%s]",
                  typeToContext.getKey(), typeToContext.getValue().getClass().getSimpleName())));
    }
  }

  /**
   * Returns a new {@link Builder} suitable for creating instances of ModuleActionContextRegistry.
   */
  public static Builder builder() {
    return new Builder();
  }

  /**
   * Builder collecting the contexts and restrictions thereon for a {@link
   * ModuleActionContextRegistry}.
   */
  public static final class Builder {

    private final List<ActionContextInformation<?>> actionContexts = new ArrayList<>();
    private final Map<Class<?>, String> typeToRestriction = new HashMap<>();

    /**
     * Restricts the registry to only return implementations for the given type if they were
     * {@linkplain #register registered} with the provided restriction as a command-line identifier.
     *
     * <p>Note that if no registered action context matches the requested command-line identifiers
     * when it is {@linkplain #build() built} then the registry will return {@code null} when
     * queried for this identifying type.
     *
     * <p>This behavior can be reset by passing an empty restriction to this method which will cause
     * the default behavior (last implementation registered for the identifying type) to be used.
     *
     * @param restriction command-line identifier used during registration of the desired
     *     implementation or {@code ""} to allow any implementation of the identifying type
     */
    public Builder restrictTo(Class<?> identifyingType, String restriction) {
      typeToRestriction.put(identifyingType, restriction);
      return this;
    }

    /**
     * Registers an action context implementation identified by the given type and which can be
     * {@linkplain #restrictTo restricted} by its provided command-line identifiers.
     */
    public <T extends ActionContext> Builder register(
        Class<T> identifyingType, T context, String... commandLineIdentifiers) {
      actionContexts.add(
          new AutoValue_ModuleActionContextRegistry_ActionContextInformation<>(
              context, identifyingType, ImmutableList.copyOf(commandLineIdentifiers)));
      return this;
    }

    /** Constructs the registry configured by this builder. */
    public ModuleActionContextRegistry build() throws AbruptExitException {
      HashSet<Class<?>> usedTypes = new HashSet<>();
      MutableClassToInstanceMap<ActionContext> contextToInstance =
          MutableClassToInstanceMap.create();
      for (ActionContextInformation<?> actionContextInformation : actionContexts) {
        Class<? extends ActionContext> identifyingType = actionContextInformation.identifyingType();
        if (typeToRestriction.containsKey(identifyingType)) {
          String restriction = typeToRestriction.get(identifyingType);
          if (!actionContextInformation.commandLineIdentifiers().contains(restriction)
              && !restriction.isEmpty()) {
            continue;
          }
        }
        usedTypes.add(identifyingType);
        actionContextInformation.addToMap(contextToInstance);
      }

      Sets.SetView<Class<?>> unusedRestrictions =
          Sets.difference(typeToRestriction.keySet(), usedTypes);
      if (!unusedRestrictions.isEmpty()) {
        throw new AbruptExitException(
            DetailedExitCode.of(
                FailureDetail.newBuilder()
                    .setMessage(getMissingIdentifierErrorMessage(unusedRestrictions).toString())
                    .setExecutionOptions(
                        FailureDetails.ExecutionOptions.newBuilder()
                            .setCode(Code.RESTRICTION_UNMATCHED_TO_ACTION_CONTEXT))
                    .build()));
      }

      return new ModuleActionContextRegistry(ImmutableClassToInstanceMap.copyOf(contextToInstance));
    }

    private StringBuilder getMissingIdentifierErrorMessage(
        Sets.SetView<Class<?>> unusedRestrictions) {
      Multimap<Class<?>, String> typeToAvailableIdentifiers = ArrayListMultimap.create();
      for (Class<?> type : unusedRestrictions) {
        for (ActionContextInformation<?> actionContextInformation : actionContexts) {
          if (actionContextInformation.identifyingType().equals(type)) {
            typeToAvailableIdentifiers.putAll(
                type, actionContextInformation.commandLineIdentifiers());
          }
        }
      }
      StringBuilder message = new StringBuilder();
      for (Map.Entry<Class<?>, Collection<String>> typeToIdentifiers :
          typeToAvailableIdentifiers.asMap().entrySet()) {
        Class<?> type = typeToIdentifiers.getKey();
        message.append(
            String.format(
                "No context of type %s registered for requested value '%s', available identifiers"
                    + " are: [%s]%n",
                type.getSimpleName(),
                typeToRestriction.get(type),
                Joiner.on(", ").join(typeToIdentifiers.getValue())));
      }
      return message;
    }
  }

  @AutoValue
  abstract static class ActionContextInformation<T extends ActionContext> {

    abstract T context();

    abstract Class<T> identifyingType();

    abstract ImmutableList<String> commandLineIdentifiers();

    private void addToMap(MutableClassToInstanceMap<ActionContext> map) {
      map.putInstance(identifyingType(), context());
    }
  }
}
