package com.usky.common.core.util;

import com.usky.common.core.exception.BusinessException;
import com.usky.common.core.exception.ErrorCode;
import org.apache.commons.collections.CollectionUtils;


import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * check相关方法, 用于判断,并抛出异常.
 * default相关方法, 类似三元表达式
 * apply相关方法, 用于判断, 并执行.
 *
 * @author barry chen
 * @date 2021/1/20 7:34 下午
 */
public final class Assert {
    private Assert() {
    }

    /**
     * 如果表达式false, 则抛出异常.
     *
     * @param expression
     * @param message
     */
    public static void check(boolean expression, String message) {
        if (!expression) {
            throw new BusinessException(message);
        }
    }

    /**
     * 如果表达式false, 则抛出异常.
     *
     * @param expression
     * @param errorCode
     * @param message
     */
    public static void check(boolean expression, ErrorCode errorCode, String message) {
        if (!expression) {
            throw new BusinessException(errorCode, message);
        }
    }

    /**
     * 如果表达式false, 则抛出异常.
     *
     * @param expression
     * @param exceptionSupplier
     */
    public static <X extends Throwable> void check(boolean expression, Supplier<? extends X> exceptionSupplier) throws X {
        if (!expression) {
            throw exceptionSupplier.get();
        }
    }

    /**
     * 判断字符串是否blank, 如果blank, 抛出异常
     *
     * @param str
     * @param message
     */
    public static void checkNotBlank(String str, String message) {
        if (StringUtils.isBlank(str)) {
            throw new BusinessException(message);
        }
    }

    /**
     * 判断字符串是否blank, 如果blank, 抛出异常
     *
     * @param str
     * @param errorCode
     * @param message
     */
    public static void checkNotBlank(String str, ErrorCode errorCode, String message) {
        if (StringUtils.isBlank(str)) {
            throw new BusinessException(errorCode, message);
        }
    }

    /**
     * 判断字符串是否blank, 如果blank, 抛出异常
     *
     * @param str
     * @param exceptionSupplier
     */
    public static <X extends Throwable> void checkNotBlank(String str, Supplier<? extends X> exceptionSupplier) throws X {
        if (StringUtils.isBlank(str)) {
            throw exceptionSupplier.get();
        }
    }

    /**
     * 判断集合是否为空, 如果空, 抛出异常
     *
     * @param collection
     * @param message
     */
    public static void checkNotEmpty(Collection<?> collection, String message) {
        if (CollectionUtils.isEmpty(collection)) {
            throw new BusinessException(message);
        }
    }

    /**
     * 判断集合是否为空, 如果空, 抛出异常
     *
     * @param collection
     * @param errorCode
     * @param message
     */
    public static void checkNotEmpty(Collection<?> collection, ErrorCode errorCode, String message) {
        if (CollectionUtils.isEmpty(collection)) {
            throw new BusinessException(errorCode, message);
        }
    }

    /**
     * 判断集合是否为空, 如果空, 抛出异常
     *
     * @param collection
     * @param exceptionSupplier
     */
    public static <X extends Throwable> void checkNotEmpty(Collection<?> collection, Supplier<? extends X> exceptionSupplier) throws X {
        if (CollectionUtils.isEmpty(collection)) {
            throw exceptionSupplier.get();
        }
    }

    /**
     * 如果assertFunction执行结果为true, 则执行runnable
     *
     * @param t
     * @param assertFunction
     * @param runnable
     * @param <T>
     */
    public static <T> void apply(T t, Function<T, Boolean> assertFunction, Runnable runnable) {
        apply(assertFunction.apply(t), runnable::run);
    }

    public static void apply(boolean expression, Runnable runnable) {
        if (expression) {
            runnable.run();
        }
    }

    /**
     * 如果assertFunction执行结果为true, 则执行consumer
     *
     * @param t
     * @param assertFunction
     * @param consumer
     * @param <T>
     */
    public static <T> void apply(T t, Function<T, Boolean> assertFunction, Consumer<T> consumer) {
        if (assertFunction.apply(t)) {
            consumer.accept(t);
        }
    }

    /**
     * 如果assertFunction执行结果为true, 则执行trueFunction, 否则执行falseFunction
     *
     * @param t
     * @param assertFunction
     * @param trueFunction
     * @param falseFunction
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> R apply(T t, Function<T, Boolean> assertFunction, Function<T, R> trueFunction, Function<T, R> falseFunction) {
        if (assertFunction.apply(t)) {
            return trueFunction.apply(t);
        } else {
            return falseFunction.apply(t);
        }
    }

    public static <T> T defaultIfNull(T t, T defaultT) {
        return defaultIfTrue(t, Objects::isNull, defaultT);
    }

    /**
     * 如果assertFunction执行结果为True, 则返回defaultT
     *
     * @param t
     * @param assertFunction
     * @param defaultT
     * @param <T>
     * @return
     */
    public static <T> T defaultIfTrue(T t, Function<T, Boolean> assertFunction, T defaultT) {
        if (assertFunction.apply(t)) {
            return defaultT;
        } else {
            return t;
        }
    }

    public static String defaultIfBlank(String str, String defaultStr) {
        return defaultIfTrue(str, StringUtils::isBlank, defaultStr);
    }

    public static Collection<?> defaultIfEmpty(Collection<?> collection, Collection<?> defaultCollection) {
        return defaultIfTrue(collection, CollectionUtils::isEmpty, defaultCollection);
    }

}
