package com.bcxin.ferry.common.exception;

import org.apache.commons.lang3.StringUtils;

/**
 * 基础运行期异常，应用中所有运行期异常均需要继承该类。 所有继承的子类按需求实现对应的构造方法
 */
public abstract class AbstractRuntimeException extends RuntimeException {
    /**
     * 详细信息
     */
    private String detailMessage;

    /**
     * 具有明细错误消息的异常
     *
     * @param detailMessage 错误消息明细
     */
    public AbstractRuntimeException(String detailMessage) {
        super();
        this.detailMessage = detailMessage;
    }

    /**
     * 具有引发异常堆栈的异常
     *
     * @param e 引发异常
     */
    public AbstractRuntimeException(Throwable e) {
        super(e);
        if (e != null) {
            this.detailMessage = e.getMessage();
        }
    }

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

    /**
     * 具有消息格式化功能的异常 消息格式化的规则请参阅{@link String#format(String, Object...)}
     *
     * @param detailMessageFormat 消息格式化模板
     * @param args 格式化参数
     */
    public AbstractRuntimeException(String detailMessageFormat, Object... args) {
        super();
        // 格式化拼装明细消息
        this.detailMessage = this.formatMessage(detailMessageFormat, args);
    }

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

    /**
     * 判断是否为其父类或者是否相等
     *
     * @param subObject 要判断的对象
     * @param parentClass 父类
     * @return
     */
    protected static boolean isSubClass(Object subObject, Class<?> parentClass) {
        if (subObject == null || parentClass == null) {
            return false;
        }
        return parentClass.isAssignableFrom(subObject.getClass());
    }

    /**
     * 格式化错误消息 如果消息模板为空，直接返回空串 如果转换失败，消息模板不为空，那么直接返回消息模板，如果为空返回空串
     *
     * @param detailMessageFormat 消息格式化模板
     * @param args 格式化参数
     * @return 格式化后字符串
     */
    private String formatMessage(String detailMessageFormat, Object... args) {
        try {
            if (StringUtils.isBlank(detailMessageFormat)) {
                // 如果需要格式化的模板为空，直接返回空串
                return "";
            }
            // 如果格式化参数为空，那么直接返回格式化模板
            if (args == null || args.length == 0) {
                return detailMessageFormat;
            }
            // 进行消息格式化
            return String.format(detailMessageFormat, args);
        } catch (Exception e) {
            // 忽略这个异常
            // 直接返回，如果转换失败，消息模板不为空，那么直接返回消息模板，如果为空返回空串
            return StringUtils.isNotBlank(detailMessageFormat) ? detailMessageFormat : "";
        }
    }

    @Override
    public String getMessage() {
        return this.detailMessage;
    }
}

