package com.bcxin.ferry.common.exception;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 断言异常
 */
public class AssertException extends AbstractRuntimeException {

    /**
     * 具有明细错误消息的异常
     *
     * @param detailMessage 错误消息明细
     */
    private AssertException(String detailMessage) {
        super(detailMessage);
    }

    /**
     * 具有引发异常堆栈的异常
     *
     * @param e 引发异常
     */
    private AssertException(Throwable e) {
        super(e);
    }

    /**
     * 具有明细消息和引发异常堆栈的异常
     *
     * @param detailMessage 错误消息明细
     * @param e
     */
    private AssertException(String detailMessage, Throwable e) {
        super(detailMessage, e);
    }

    /**
     * 具有消息格式化功能的异常 消息格式化的规则请参阅{@link String#format(String, Object...)}
     *
     * @param detailMessageFormat 消息格式化模板
     * @param args
     */
    private AssertException(String detailMessageFormat, Object... args) {
        super(detailMessageFormat, args);
    }

    /**
     * 具有明细消息和引发异常堆栈的异常，具有消息格式化功能 消息格式化的规则请参阅{@link String#format(String, Object...)}
     *
     * @param e 引发异常
     * @param detailMessageFormat 消息格式化模板
     * @param args
     */
    private AssertException(Throwable e, String detailMessageFormat, Object... args) {
        super(e, detailMessageFormat, args);
    }

    /**
     * 具有引发异常堆栈的异常
     *
     * @param e 引发异常
     */
    public static AssertException exception(Throwable e) {
        return new AssertException(e);
    }

    /**
     * 具有明细消息和引发异常堆栈的异常
     *
     * @param detailMessage 错误消息明细
     * @param e
     */
    public static AssertException exception(String detailMessage, Throwable e) {
        return new AssertException(detailMessage, e);
    }

    /**
     * 具有消息格式化功能的异常 消息格式化的规则请参阅{@link String#format(String, Object...)}
     * 格式化参数如果小于需要格式化的个数那么无法进行格式化，如果大于则没有影响
     *
     * @param detailMessageFormat 消息格式化模板
     * @param args
     */
    public static AssertException exception(String detailMessageFormat, Object... args) {
        if (StringUtils.isBlank(detailMessageFormat)) {
            return exception("未知异常");
        }
        if (ArrayUtils.isEmpty(args)) {
            return exception(detailMessageFormat);
        }
        Object lastArg = args[args.length - 1];
        if (isSubClass(lastArg, Throwable.class)) {
            return new AssertException((Throwable) lastArg, detailMessageFormat, ArrayUtils.subarray(args, 0, (args.length - 1)));
        }
        return new AssertException(detailMessageFormat, args);
    }

    /**
     * 具有明细错误消息的异常
     *
     * @param detailMessage 错误消息明细
     */
    public static AssertException exception(String detailMessage) {
        return new AssertException(detailMessage);
    }
}
