package cn.skcks.docking.gb28181.wvp.utils;

import cn.skcks.docking.gb28181.common.json.JsonResponse;
import com.github.rholder.retry.*;
import com.google.common.base.Predicate;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

@Slf4j
@SuppressWarnings("UnstableApiUsage")
public class RetryUtil {
    /**
     * 默认重试次数
     */
    public final static int DEFAULT_RETRY_TIME = 3;
    /**
     * 默认每次重试等待时间
     */
    public final static long DEFAULT_RETRY_INTERVAL = 3;
    public final static TimeUnit DEFAULT_RETRY_INTERVAL_UNIT = TimeUnit.SECONDS;

    public static RetryListener defaultRetryListener(String name) {
        return new RetryListener() {
            @Override
            public <V> void onRetry(Attempt<V> attempt) {
                log.info("第 {} 次 执行 {} 结束", attempt.getAttemptNumber(), name);
                if (attempt.hasException()) {
                    log.info("执行 {} 异常 {}", name, attempt.getExceptionCause().getMessage());
                }
            }
        };
    }

    public static <T> Predicate<JsonResponse<T>> defaultRetryIf(){
        return result -> result == null || (result.getCode() != 0 && result.getCode() != 200);
    }

    public static Predicate<JsonResponse<?>> defaultGenericRetryIf(){
        return result -> result == null || (result.getCode() != 0 && result.getCode() != 200);
    }

    public static <T> RetryerBuilder<JsonResponse<T>> getDefaultRetryerBuilder(String name, int waitTime, TimeUnit waitUnit, int retryTime) {
        return RetryerBuilder.<JsonResponse<T>>newBuilder()
                // 异常就重试
                .retryIfException()
                .retryIfRuntimeException()
                // 重试间隔
                .withWaitStrategy(WaitStrategies.fixedWait(waitTime, waitUnit))
                // 重试次数
                .withStopStrategy(StopStrategies.stopAfterAttempt(retryTime))
                .retryIfResult(defaultRetryIf())
                .withRetryListener(defaultRetryListener(name));
    }

    public static <T> RetryerBuilder<JsonResponse<T>> getDefaultRetryerBuilder(String name) {
        return RetryerBuilder.<JsonResponse<T>>newBuilder()
                // 异常就重试
                .retryIfException()
                .retryIfRuntimeException();
    }


    public static <T> Retryer<JsonResponse<T>> getDefaultRetryer(String name) {
        return RetryUtil.<T>getDefaultRetryerBuilder(name)
                // 重试间隔
                .withWaitStrategy(WaitStrategies.fixedWait(DEFAULT_RETRY_INTERVAL, TimeUnit.SECONDS))
                // 重试次数
                .withStopStrategy(StopStrategies.stopAfterAttempt(DEFAULT_RETRY_TIME))
                .retryIfResult(defaultRetryIf())
                .withRetryListener(defaultRetryListener(name))
                .build();
    }

    public static RetryerBuilder<JsonResponse<?>> getDefaultGenericRetryerBuilder(String name, int retryTime, long retryInterval, TimeUnit retryTimeUnit,RetryListener retryListener) {
        return RetryerBuilder.<JsonResponse<?>>newBuilder()
                // 异常就重试
                .retryIfException()
                .retryIfRuntimeException()
                // 重试间隔
                .withWaitStrategy(WaitStrategies.fixedWait(retryInterval, retryTimeUnit))
                // 重试次数
                .withStopStrategy(StopStrategies.stopAfterAttempt(retryTime))
                .retryIfResult(defaultGenericRetryIf())
                .withRetryListener(retryListener);
    }

    public static RetryerBuilder<JsonResponse<?>> getDefaultGenericRetryerBuilder(String name) {
        return getDefaultGenericRetryerBuilder(name, DEFAULT_RETRY_TIME, DEFAULT_RETRY_INTERVAL, DEFAULT_RETRY_INTERVAL_UNIT, defaultRetryListener(name));
    }

    public static Retryer<JsonResponse<?>> getDefaultGenericRetryer(String name, int retryTime, long retryInterval, TimeUnit retryTimeUnit, RetryListener retryListener) {
        return getDefaultGenericRetryerBuilder(name, retryTime, retryInterval, retryTimeUnit, retryListener).build();
    }

    public static Retryer<JsonResponse<?>> getDefaultGenericRetryer(String name, int retryTime, long retryInterval, TimeUnit retryTimeUnit) {
        return getDefaultGenericRetryer(name, retryTime, retryInterval, retryTimeUnit, defaultRetryListener(name));
    }

    public static Retryer<JsonResponse<?>> getDefaultGenericRetryer(String name, int retryTime, long retryInterval) {
        return getDefaultGenericRetryer(name, retryTime, retryInterval, DEFAULT_RETRY_INTERVAL_UNIT);
    }

    public static Retryer<JsonResponse<?>> getDefaultGenericRetryer(String name) {
        return getDefaultGenericRetryer(name, DEFAULT_RETRY_TIME, DEFAULT_RETRY_INTERVAL);
    }

}
