// Copyright 2014 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.util;

import com.google.common.base.Objects;
import com.google.errorprone.annotations.Immutable;
import java.util.Collection;
import java.util.HashMap;
import javax.annotation.Nullable;

/**
 * Anything marked FAILURE is generally from a problem with the source code under consideration. In
 * these cases, a re-run in an identical client should produce an identical return code all things
 * being constant.
 *
 * <p>Anything marked as an ERROR is generally a problem unrelated to the source code itself. It is
 * either something wrong with the user's command line or the user's machine or environment.
 *
 * <p>Note that these exit codes should be kept consistent with the codes returned by Blaze's
 * launcher in //devtools/blaze/main:blaze.cc Blaze exit codes should be consistently classified as
 * permanent vs. transient (i.e. retriable) vs. unknown transient/permanent because users, in
 * particular infrastructure users, will use the exit code to decide whether the request should be
 * retried or not.
 */
@Immutable
public final class ExitCode {
  // Tracks all exit codes defined here and elsewhere in Bazel.
  private static final HashMap<Integer, ExitCode> exitCodeRegistry = new HashMap<>();

  public static final ExitCode SUCCESS = ExitCode.create(0, "SUCCESS");
  public static final ExitCode BUILD_FAILURE = ExitCode.create(1, "BUILD_FAILURE");
  public static final ExitCode PARSING_FAILURE = ExitCode.createUnregistered(1, "PARSING_FAILURE");
  public static final ExitCode COMMAND_LINE_ERROR = ExitCode.create(2, "COMMAND_LINE_ERROR");
  public static final ExitCode TESTS_FAILED = ExitCode.create(3, "TESTS_FAILED");
  public static final ExitCode PARTIAL_ANALYSIS_FAILURE =
      ExitCode.createUnregistered(3, "PARTIAL_ANALYSIS_FAILURE");
  public static final ExitCode NO_TESTS_FOUND = ExitCode.create(4, "NO_TESTS_FOUND");
  public static final ExitCode RUN_FAILURE = ExitCode.create(6, "RUN_FAILURE");
  public static final ExitCode ANALYSIS_FAILURE = ExitCode.create(7, "ANALYSIS_FAILURE");
  public static final ExitCode INTERRUPTED = ExitCode.create(8, "INTERRUPTED");
  public static final ExitCode LOCK_HELD_NOBLOCK_FOR_LOCK =
      ExitCode.create(9, "LOCK_HELD_NOBLOCK_FOR_LOCK");

  public static final ExitCode REMOTE_ENVIRONMENTAL_ERROR =
      ExitCode.createInfrastructureFailure(32, "REMOTE_ENVIRONMENTAL_ERROR");
  public static final ExitCode OOM_ERROR = ExitCode.createInfrastructureFailure(33, "OOM_ERROR");

  public static final ExitCode REMOTE_ERROR =
      ExitCode.createInfrastructureFailure(34, "REMOTE_ERROR");
  public static final ExitCode LOCAL_ENVIRONMENTAL_ERROR =
      ExitCode.createInfrastructureFailure(36, "LOCAL_ENVIRONMENTAL_ERROR");
  public static final ExitCode BLAZE_INTERNAL_ERROR =
      ExitCode.createInfrastructureFailure(37, "BLAZE_INTERNAL_ERROR");
  public static final ExitCode TRANSIENT_BUILD_EVENT_SERVICE_UPLOAD_ERROR =
      ExitCode.createInfrastructureFailure(38, "PUBLISH_ERROR");
  public static final ExitCode REMOTE_CACHE_EVICTED =
      ExitCode.createInfrastructureFailure(39, "REMOTE_CACHE_EVICTED");
  public static final ExitCode PERSISTENT_BUILD_EVENT_SERVICE_UPLOAD_ERROR =
      ExitCode.create(45, "PERSISTENT_BUILD_EVENT_SERVICE_UPLOAD_ERROR");
  public static final ExitCode EXTERNAL_DEPS_ERROR = ExitCode.create(48, "EXTERNAL_DEPS_ERROR");

  /**
   * Creates and returns an ExitCode.  Requires a unique exit code number.
   *
   * @param code the int value for this exit code
   * @param name a human-readable description
   */
  public static ExitCode create(int code, String name) {
    return new ExitCode(code, name, /*infrastructureFailure=*/false, /*register=*/true);
  }

  /**
   * Creates and returns an ExitCode that represents an infrastructure failure.
   *
   * @param code the int value for this exit code
   * @param name a human-readable description
   */
  public static ExitCode createInfrastructureFailure(int code, String name) {
    return new ExitCode(code, name, /*infrastructureFailure=*/true, /*register=*/true);
  }

  /**
   * Creates and returns an ExitCode that has the same numeric code as another ExitCode. This is to
   * allow the duplicate error codes listed above to be registered, but is private to prevent other
   * users from creating duplicate error codes in the future.
   *
   * @param code the int value for this exit code
   * @param name a human-readable description
   */
  private static ExitCode createUnregistered(int code, String name) {
    return new ExitCode(code, name, /*infrastructureFailure=*/false, /*register=*/false);
  }

  /**
   * Add the given exit code to the registry.
   *
   * @param exitCode the exit code to register
   * @throws IllegalStateException if the numeric exit code is already in the registry.
   */
  private static void register(ExitCode exitCode) {
    synchronized (exitCodeRegistry) {
      int codeNum = exitCode.getNumericExitCode();
      if (exitCodeRegistry.containsKey(codeNum)) {
        throw new IllegalStateException(
            "Exit code " + codeNum + " (" + exitCode.name + ") already registered");
      }
      exitCodeRegistry.put(codeNum, exitCode);
    }
  }

  /**
   * Returns all registered ExitCodes.
   */
  public static Collection<ExitCode> values() {
    synchronized (exitCodeRegistry) {
      return exitCodeRegistry.values();
    }
  }

  /**
   * Returns a registered {@link ExitCode} with the given {@code code}.
   *
   * <p>Note that there *are* unregistered ExitCodes. This will never return them.
   */
  @Nullable
  static ExitCode forCode(int code) {
    synchronized (exitCodeRegistry) {
      return exitCodeRegistry.get(code);
    }
  }

  private final int numericExitCode;
  private final String name;
  private final boolean infrastructureFailure;

  /**
   * Whenever a new exit code is created, it is registered (to prevent exit codes with identical
   * numeric codes from being created).  However, there are some exit codes in this file that have
   * duplicate numeric codes, so these are not registered.
   */
  private ExitCode(int exitCode, String name, boolean infrastructureFailure, boolean register) {
    this.numericExitCode = exitCode;
    this.name = name;
    this.infrastructureFailure = infrastructureFailure;
    if (register) {
      ExitCode.register(this);
    }
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(numericExitCode, name, infrastructureFailure);
  }

  @Override
  public boolean equals(Object object) {
    if (object instanceof ExitCode) {
      ExitCode that = (ExitCode) object;
      return this.numericExitCode == that.numericExitCode
          && this.name.equals(that.name)
          && this.infrastructureFailure == that.infrastructureFailure;
    }
    return false;
  }

  /**
   * Returns the human-readable name for this exit code.  Not guaranteed to be stable, use the
   * numeric exit code for that.
   */
  @Override
  public String toString() {
    return name;
  }

  /**
   * Returns the error's int value.
   */
  public int getNumericExitCode() {
    return numericExitCode;
  }

  /**
   * Returns the human-readable name.
   */
  public String name() {
    return name;
  }

  /**
   * Returns true if the current exit code represents a failure of Blaze infrastructure,
   * vs. a build failure.
   */
  public boolean isInfrastructureFailure() {
    return infrastructureFailure;
  }
}
