// Copyright (C) 2019 The Android Open Source Project
//
// 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.gerrit.server;

import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.server.project.ProjectConfig;
import java.util.Optional;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.RefUpdate;

/**
 * Class to detect and handle exceptions that are caused by temporary errors, and hence should cause
 * a retry of the failed operation.
 */
public class ExceptionHookImpl implements ExceptionHook {
  private static final String LOCK_FAILURE_USER_MESSAGE =
      "Updating a ref failed with LOCK_FAILURE.\n"
          + "This may be a temporary issue due to concurrent updates.\n"
          + "Please retry later.";
  private static final String INVALID_PROJECT_CONFIG_USER_MESSAGE =
      "Invalid " + ProjectConfig.PROJECT_CONFIG + " file.";
  private static final String CONTACT_PROJECT_OWNER_USER_MESSAGE =
      "Please contact the project owner.";

  @Override
  public boolean shouldRetry(String actionType, String actionName, Throwable throwable) {
    return isLockFailure(throwable);
  }

  @Override
  public boolean skipRetryWithTrace(String actionType, String actionName, Throwable throwable) {
    return isInvalidProjectConfig(throwable);
  }

  @Override
  public Optional<String> formatCause(Throwable throwable) {
    if (isLockFailure(throwable)) {
      return Optional.of(RefUpdate.Result.LOCK_FAILURE.name());
    }
    if (isMissingObjectException(throwable)) {
      return Optional.of("missing_object");
    }
    if (isInvalidProjectConfig(throwable)) {
      return Optional.of("invalid_project_config");
    }
    return Optional.empty();
  }

  @Override
  public ImmutableList<String> getUserMessages(Throwable throwable, @Nullable String traceId) {
    if (isLockFailure(throwable)) {
      return ImmutableList.of(LOCK_FAILURE_USER_MESSAGE);
    }
    if (isInvalidProjectConfig(throwable)) {
      return ImmutableList.of(
          getInvalidConfigMessage(throwable).orElse(INVALID_PROJECT_CONFIG_USER_MESSAGE)
              + "\n"
              + CONTACT_PROJECT_OWNER_USER_MESSAGE);
    }
    return ImmutableList.of();
  }

  @Override
  public Optional<Status> getStatus(Throwable throwable) {
    if (isLockFailure(throwable)) {
      return Optional.of(Status.create(503, "Lock failure"));
    }
    if (isInvalidProjectConfig(throwable)) {
      return Optional.of(Status.create(409, "Conflict"));
    }
    return Optional.empty();
  }

  private static boolean isLockFailure(Throwable throwable) {
    return isMatching(throwable, t -> t instanceof LockFailureException);
  }

  private static boolean isMissingObjectException(Throwable throwable) {
    return isMatching(throwable, t -> t instanceof MissingObjectException);
  }

  private static boolean isInvalidProjectConfig(Throwable throwable) {
    return isMatching(
        throwable,
        t ->
            t instanceof InvalidConfigFileException
                && ProjectConfig.PROJECT_CONFIG.equals(
                    ((InvalidConfigFileException) t).getFileName()));
  }

  private Optional<String> getInvalidConfigMessage(Throwable throwable) {
    return Throwables.getCausalChain(throwable).stream()
        .filter(InvalidConfigFileException.class::isInstance)
        .map(ex -> ex.getMessage())
        .findFirst();
  }

  /**
   * Check whether the given exception or any of its causes matches the given predicate.
   *
   * @param throwable Exception that should be tested
   * @param predicate predicate to check if a throwable matches
   * @return {@code true} if the given exception or any of its causes matches the given predicate
   */
  private static boolean isMatching(Throwable throwable, Predicate<Throwable> predicate) {
    return Throwables.getCausalChain(throwable).stream().anyMatch(predicate);
  }
}
