// Copyright 2020 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.remote;

import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.Durations;
import com.google.rpc.DebugInfo;
import com.google.rpc.Help;
import com.google.rpc.LocalizedMessage;
import com.google.rpc.PreconditionFailure;
import com.google.rpc.PreconditionFailure.Violation;
import com.google.rpc.RequestInfo;
import com.google.rpc.ResourceInfo;
import com.google.rpc.RetryInfo;
import com.google.rpc.Status;
import io.grpc.Status.Code;
import io.grpc.protobuf.StatusProto;

/** Specific retry logic for execute request with gapi Status. */
class ExecuteRetrier extends RemoteRetrier {

  private static final String VIOLATION_TYPE_MISSING = "MISSING";

  private static class RetryInfoBackoff implements Backoff {
    private final int maxRetryAttempts;
    int retries = 0;

    RetryInfoBackoff(int maxRetryAttempts) {
      this.maxRetryAttempts = maxRetryAttempts;
    }

    @Override
    public long nextDelayMillis(Exception e) {
      if (retries >= maxRetryAttempts) {
        return -1;
      }
      RetryInfo retryInfo = getRetryInfo(e);
      retries++;
      return Durations.toMillis(retryInfo.getRetryDelay());
    }

    RetryInfo getRetryInfo(Exception e) {
      RetryInfo retryInfo = RetryInfo.getDefaultInstance();
      Status status = StatusProto.fromThrowable(e);
      if (status != null) {
        for (Any detail : status.getDetailsList()) {
          if (detail.is(RetryInfo.class)) {
            try {
              retryInfo = detail.unpack(RetryInfo.class);
            } catch (InvalidProtocolBufferException protoEx) {
              // really shouldn't happen, ignore
            }
          }
        }
      }
      return retryInfo;
    }

    @Override
    public int getRetryAttempts() {
      return retries;
    }
  }

  ExecuteRetrier(
      int maxRetryAttempts,
      ListeningScheduledExecutorService retryService,
      CircuitBreaker circuitBreaker) {
    super(
        () -> maxRetryAttempts > 0 ? new RetryInfoBackoff(maxRetryAttempts) : RETRIES_DISABLED,
        ExecuteRetrier::shouldRetry,
        retryService,
        circuitBreaker);
  }

  private static boolean shouldRetry(Exception e) {
    if (BulkTransferException.isOnlyCausedByCacheNotFoundException(e)) {
      return true;
    }
    Status status = StatusProto.fromThrowable(e);
    if (status == null || status.getDetailsCount() == 0) {
      return false;
    }
    boolean failedPrecondition = status.getCode() == Code.FAILED_PRECONDITION.value();
    for (Any detail : status.getDetailsList()) {
      if (detail.is(RetryInfo.class)) {
        // server says we can retry, regardless of other details
        return true;
      } else if (failedPrecondition) {
        if (detail.is(PreconditionFailure.class)) {
          try {
            PreconditionFailure f = detail.unpack(PreconditionFailure.class);
            if (f.getViolationsCount() == 0) {
              failedPrecondition = false;
            }
            for (Violation v : f.getViolationsList()) {
              if (!v.getType().equals(VIOLATION_TYPE_MISSING)) {
                failedPrecondition = false;
              }
            }
            // if *all* > 0 precondition failure violations have type MISSING, failedPrecondition
            // remains true
          } catch (InvalidProtocolBufferException protoEx) {
            // really shouldn't happen
            return false;
          }
        } else if (!(detail.is(DebugInfo.class)
            || detail.is(Help.class)
            || detail.is(LocalizedMessage.class)
            || detail.is(RequestInfo.class)
            || detail.is(ResourceInfo.class))) { // ignore benign details
          // consider all other details as failures
          failedPrecondition = false;
        }
      }
    }
    return failedPrecondition;
  }
}
