package cn.com.ty.lift.common.judge;

import cn.hutool.core.util.ObjectUtil;

import java.lang.reflect.Field;

/**
 * <p>
 *     条件判断，如果不符合条件，抛出异常
 * </p>
 * @author wcz
 * @since  2020/1/9 8:46
 */
public interface Judge {

    String IDENTIFIER_INVALID       = "标识ID无效";
    String MUST_GT0                 = "数值必须大于0";
    String MUST_LT0                 = "数值必须小于0";
    String MUST_EQ0                 = "数值必须等于0";
    String MUST_NGT0                = "数值必须大于或等于0";
    String MUST_NLT0                = "数值必须小于或等于0";
    String MUST_NEQ0                = "数值必须不等于0";
    String DATA_MISSING_INCORRECT   = "缺少数据或数据有误";
    String DATA_INVALID_CONDITIONS  = "数据无效或条件不成立";
    String PARAMETER_VERIFY_FAIL    = "参数校验失败";
    String PARAMETER_FILED_MISSING  = "缺少参数属性值域";

    static JudgeException judgeException(){
        return new JudgeException(DATA_MISSING_INCORRECT);
    }

    static JudgeException judgeException(String message){
        if(null == message || message.length() == 0){
            return judgeException();
        }
        return new JudgeException(message);
    }
    static JudgeException judgeException(String message, Throwable cause){
        if(null == message || message.length() == 0 || null == cause){
            return new JudgeException(DATA_MISSING_INCORRECT, new IllegalArgumentException());
        }
        return new JudgeException(message, cause);
    }
    /**
     * id == null || id <= 0 throw new JudgeException(message)
     * @param id id值
     * @param message 抛出异常消息
     */
    static void id(Long id, String message) {
        notNull(id, message);
        if (id <= 0) {
            throw judgeException(message);
        }
    }

    /**
     * id == null || id <= 0 throw new JudgeException(IDENTIFIER_INVALID)
     *
     * @param ids 不定个id值
     */
    static void id(Long... ids) {
        notNull(ids, IDENTIFIER_INVALID);
        for (Long id : ids) {
            if (null == id || id <= 0) {
                throw judgeException(IDENTIFIER_INVALID);
            }
        }
    }

    /**
     * value == null || value <= 0 throw new JudgeException(message);
     *
     * @param value 数值型的参数值
     * @param message 抛出异常中的消息
     */
    static void gt0(Number value, String message) {
        if (null == value) {
            throw judgeException(message);
        }
        if (value instanceof Long && value.longValue() <= 0) {
            throw judgeException(message);
        }
        if (value instanceof Integer && value.intValue() <= 0) {
            throw judgeException(message);
        }
        if (value instanceof Float && value.floatValue() <= 0) {
            throw judgeException(message);
        }
        if (value instanceof Double && value.doubleValue() <= 0) {
            throw judgeException(message);
        }
    }

    /**
     * value == null || value <= 0 throw new JudgeException(message);
     *
     * @param values 不定个数的数值型的值
     */
    static void gt0(Number... values) {
        notNull(values, MUST_GT0);
        for (Number value : values) {
            gt0(value, MUST_GT0);
        }
    }

    /**
     * value == null || value >= 0 throw new JudgeException(message);
     *
     * @param value 数值型的值
     * @param message 抛出异常的消息值
     */
    static void lt0(Number value, String message) {
        if (null == value) {
            throw judgeException(message);
        }
        if (value instanceof Long && value.longValue() >= 0) {
            throw judgeException(message);
        }
        if (value instanceof Integer && value.intValue() >= 0) {
            throw judgeException(message);
        }
        if (value instanceof Float && value.floatValue() >= 0) {
            throw judgeException(message);
        }
        if (value instanceof Double && value.doubleValue() >= 0) {
            throw judgeException(message);
        }
    }

    /**
     * value == null || value >= 0 throw new JudgeException(message);
     *
     * @param values 一个或多个的数值
     */
    static void lt0(Number... values) {
        notNull(values, MUST_LT0);
        for (Number value : values) {
            lt0(value, MUST_LT0);
        }
    }

    /**
     * value == null || value != 0 throw new JudgeException(message);
     *
     * @param value 数值型的值
     * @param message 抛出异常的消息
     */
    static void eq0(Number value, String message) {
        if (null == value) {
            throw judgeException(message);
        }
        if (value instanceof Long && value.longValue() != 0) {
            throw judgeException(message);
        }
        if (value instanceof Integer && value.intValue() != 0) {
            throw judgeException(message);
        }
        if (value instanceof Float && value.floatValue() != 0) {
            throw judgeException(message);
        }
        if (value instanceof Double && value.doubleValue() != 0) {
            throw judgeException(message);
        }
    }

    /**
     * value == null || value != 0 throw new JudgeException(message);
     * @param values 一个或多个数的数值
     */
    static void eq0(Number... values) {
        notNull(values, MUST_EQ0);
        for (Number value : values) {
            eq0(value, MUST_EQ0);
        }
    }

    /**
     * value == null || value < 0 throw new JudgeException(message)
     *
     * @param value 数值型的值
     * @param message 抛出异常的消息
     */
    static void ngt0(Number value, String message) {
        if (null == value) {
            throw judgeException(message);
        }
        if (value instanceof Long && value.longValue() < 0) {
            throw judgeException(message);
        }
        if (value instanceof Integer && value.intValue() < 0) {
            throw judgeException(message);
        }
        if (value instanceof Float && value.floatValue() < 0) {
            throw judgeException(message);
        }
        if (value instanceof Double && value.doubleValue() < 0) {
            throw judgeException(message);
        }
    }

    /**
     * value == null || value < 0 throw new JudgeException(message);
     *
     * @param values 一个或多个数的数值型的值
     */
    static void ngt0(Number... values) {
        notNull(values, MUST_NGT0);
        for (Number value : values) {
            ngt0(value, MUST_NGT0);
        }
    }

    /**
     * value == null || value > 0 throw new JudgeException(message);
     *
     * @param value 数值型的值
     * @param message 抛出异常的消息
     */
    static void nlt0(Number value, String message) {
        if (null == value) {
            throw judgeException(message);
        }
        if (value instanceof Long && value.longValue() > 0) {
            throw judgeException(message);
        }
        if (value instanceof Integer && value.intValue() > 0) {
            throw judgeException(message);
        }
        if (value instanceof Float && value.floatValue() > 0) {
            throw judgeException(message);
        }
        if (value instanceof Double && value.doubleValue() > 0) {
            throw judgeException(message);
        }
    }

    /**
     * value == null || value > 0 throw new JudgeException(message);
     *
     * @param values 一个或多个数的数值
     */
    static void nlt0(Number... values) {
        notNull(values, MUST_NLT0);
        for (Number value : values) {
            nlt0(value, MUST_NLT0);
        }
    }

    /**
     * value == null || value == 0 throw new JudgeException(message);
     *
     * @param value 数值型的值
     * @param message 抛出异常的消息
     */
    static void neq0(Number value, String message) {
        if (null == value) {
            throw judgeException(message);
        }
        if (value instanceof Long && value.longValue() == 0) {
            throw judgeException(message);
        }
        if (value instanceof Integer && value.intValue() == 0) {
            throw judgeException(message);
        }
        if (value instanceof Float && value.floatValue() == 0) {
            throw judgeException(message);
        }
        if (value instanceof Double && value.doubleValue() == 0) {
            throw judgeException(message);
        }
    }

    /**
     * value == null || value != 0 throw new JudgeException(message);
     *
     * @param values 一个或多个数的数值
     */
    static void neq0(Number... values) {
        notNull(values, MUST_NEQ0);
        for (Number value : values) {
            neq0(value, MUST_NEQ0);
        }
    }

    /**
     * 判断对象object是否为空，如果不为空,直接抛出异常，返回message
     *
     * @param object 参数值
     * @param message 抛出异常的消息
     */
    static void isNull(Object object, String message) {
        if (ObjectUtil.isNotEmpty(object)) {
            throw judgeException(message);
        }
    }

    /**
     * 判断对象object是否为空，如果不为空,直接抛出异常，返回默认消息
     *
     * @param object 参数值
     */
    static void isNull(Object object) {
        isNull(object, DATA_MISSING_INCORRECT);
    }

    /**
     * 判断对象object是否为空，如果为真,直接抛出异常，返回message
     *
     * @param object 参数值
     * @param message 抛出异常的消息
     */
    static void notNull(Object object, String message) {
        if (ObjectUtil.isEmpty(object)) {
            throw judgeException(message);
        }
    }

    /**
     * 判断对象object是否为空，如果为真,直接抛出异常，返回默认消息
     *
     * @param object 参数值
     */
    static void notNull(Object object) {
        notNull(object, DATA_MISSING_INCORRECT);
    }

    /**
     * 判断表达式是否为真，如果为假，直接抛出异常，返回message
     *
     * @param expression 需要判断的布尔表达式
     * @param message 抛出异常的消息
     */
    static void isTrue(boolean expression, String message) {
        if (!expression) {
            throw judgeException(message);
        }
    }

    /**
     * 判断表达式是否为真，如果为假，直接抛出异常，返回
     *
     * @param expression 需要判断的布尔表达式
     */
    static void isTrue(boolean expression) {
        isTrue(expression, DATA_INVALID_CONDITIONS);
    }

    /**
     * 判断表达式是否为真，如果为真，直接抛出异常，返回message
     *
     * @param expression 需要判断的布尔表达式
     * @param message 抛出异常的消息
     */
    static void notTrue(boolean expression, String message) {
        if (expression) {
            throw judgeException(message);
        }
    }

    /**
     * 判断表达式是否为真，如果为真，直接抛出异常，返回
     *
     * @param expression 需要判断的布尔表达式
     */
    static void notTrue(boolean expression) {
        notTrue(expression, DATA_INVALID_CONDITIONS);
    }

    /**
     * 根据属性名检查object中是否有效值,
     * 数值型的值，必须!null && > 0 ,否则 throw new JudgeException(message)
     * message：对应object中属性用@Judger标识中的message
     * @param object 校验的对象
     * @param fields 需要校验的属性名
     */
    static void judgement(Object object, String... fields) {
        notNull(object);
        notNull(fields);
        Class<?> objectClass = object.getClass();
        notNull(objectClass);
        try {
            for (String field : fields) {
                Field declaredField = objectClass.getDeclaredField(field);
                declaredField.setAccessible(true);
                Judger judger = declaredField.getDeclaredAnnotation(Judger.class);
                Class<?> fieldClass = declaredField.getType();
                Object value = declaredField.get(object);
                if (Number.class.isAssignableFrom(fieldClass)) {
                    gt0((Number) value, null == judger ? MUST_GT0 : judger.message());
                } else {
                    notNull(value, null == judger ? DATA_MISSING_INCORRECT : judger.message());
                }
            }
        } catch (JudgeException e) {
            throw judgeException(e.getMessage());
        } catch (NoSuchFieldException e) {
            throw judgeException(PARAMETER_FILED_MISSING);
        } catch (Exception e) {
            throw judgeException(PARAMETER_VERIFY_FAIL);
        }
    }

    //======================年检相关状态值和判断方法======================================

    interface Inspection{
        /**
         * 年检未开始0
         */
        int STEP_NOT_START                          = 0;

        /**
         * 判断年检是否开始
         * @param step
         * @return
         */
        static boolean notStart(int step){
            return STEP_NOT_START == step;
        }
        /**
         * 年检 第一阶段
         */
        int STEP_ONE                                = 1;

        /**
         * 判断是否为年检阶段一
         * @param step
         * @return
         */
        static boolean stepOne(int step){
            return STEP_ONE == step;
        }
        /**
         * 年检 第二阶段
         */
        int STEP_TWO                                = 2;

        /**
         * 判断是否为年检阶段二
         * @param step
         * @return
         */
        static boolean stepTwo(int step){
            return STEP_TWO == step;
        }
        /**
         * 年检 第三阶段
         */
        int STEP_THREE                              = 3;

        /**
         * 判断是否为年检阶段三
         * @param step
         * @return
         */
        static boolean stepThree(int step){
            return STEP_THREE == step;
        }
        /**
         * 年检 第四阶段
         */
        int STEP_FOUR                               = 4;

        /**
         * 判断是否为年检阶段四
         * @param step
         * @return
         */
        static boolean stepFour(int step){
            return STEP_FOUR == step;
        }

        /**
         * 0 年检计划初始状态
         */
        int STATUS_NOT_START                        = 0;

        static boolean statusNotStart(int status){
            return STEP_NOT_START == status;
        }
        /**
         * 1  维保工确认年检计划
         */
        int STATUS_CONFIRM                          = 1;
        String confirm                              = "请确认年检计划";

        static boolean statusConfirm(int status){
            return STATUS_CONFIRM == status;
        }
        /**
         * 2  维保工上传自检报告,选择自检时间 或者 文员设置 是否检查限速器和荷载年检设置，
         *             文员也可以上传自检报告或者确认自检报告和自检时间，自检时间以最后设置的为准
         */
        int STATUS_SELFCHECK                        = 2;

        String selfcheckUpload                      = "请完善自检报告信息";
        String selfcheckDate                        = "请设置自检时间";
        String selfcheckReportImg                   = "请设置自检报告";

        static boolean statusSelfcheck(int status){
            return STATUS_SELFCHECK == status;
        }
        /**
         * 3  企业文员确认现场检验时间
         *             录入人员信息，政府质检，企业质检，联系电话
         */
        int STATUS_CHECK_CONFIRM                    = 3;
        String checkConfirm                         = "请确认检验结果";
        String checkDate                            = "请设置现场检验时间";
        String checkResultImg                       = "请设置现场检验结果";
        String inspector                            = "请设置政府质检人员";
        String operator                             = "请设置公司质检人员";
        String telephone                            = "请设置人员联系电话";

        static boolean statusCheckConfirm(int status){
            return STATUS_CHECK_CONFIRM == status;
        }
        /**
         * 4	维保工上传检验结果
         */
        int STATUS_CHECK_UPLOAD                     = 4;

        static boolean statusCheckUpload(int status){
            return STATUS_CHECK_UPLOAD == status;
        }
        /**
         * 5	企业文员确认检验结果-合格 --> 不能算年检超期
         */
        int STATUS_CHECK_QUALIFIED                  = 5;

        static boolean statusCheckQualified(int status){
            return STATUS_CHECK_QUALIFIED == status;
        }
        /**
         * 6	企业文员确认检验结果-整改 --> 回到第二阶段
         */
        int STATUS_CHECK_RECTIFICATION              = 6;

        static boolean statusCheckRectification(int status){
            return STATUS_CHECK_RECTIFICATION == status;
        }
        /**
         * 7	企业文员确认检验结果-不合格 --> 可以算年检超期
         */
        int STATUS_CHECK_UNQUALIFIED                = 7;

        static boolean statusCheckUnqualified(int status){
            return STATUS_CHECK_UNQUALIFIED == status;
        }
        /**
         * 8	维保工上传年检报告和合格证
         */
        int STATUS_CERTIFICATE_REPORT_UPLOAD        = 8;
        String certificateReportUpload              = "请上传年检报告和合格证";

        static boolean statusCertificateReportUpload(int status){
            return STATUS_CERTIFICATE_REPORT_UPLOAD == status;
        }
        /**
         * 9	企业文员确认年检报告和合格证-合格
         */
        int STATUS_CERTIFICATE_REPORT_QUALIFIED     = 9;
        String nextInspectionTime                   = "请设置下次年检时间";

        static boolean statusCertificateReportQualified(int status){
            return STATUS_CERTIFICATE_REPORT_QUALIFIED == status;
        }
        /**
         * 10	企业文员确认年检报告和合格证-不合格 -->停用电梯
         */
        int STATUS_CERTIFICATE_REPORT_UNQUALIFIED   = 10;

        static boolean statusCertificateReportUnqualified(int status){
            return STATUS_CERTIFICATE_REPORT_UNQUALIFIED == status;
        }
        String statusError                          = "年检状态有误";

        /**
         * 根据年检的状态值返回成年检的状态阶段
         * @param stepStatus 年检状态值
         * @return int
         */
        static int status2StepName(Integer stepStatus){
            int stepName;
            switch (stepStatus){
                case STATUS_NOT_START:
                    stepName = 0;
                    break;
                case STATUS_CONFIRM:
                case STATUS_SELFCHECK:
                    stepName = 1;
                    break;
                case STATUS_CHECK_CONFIRM:
                    stepName = 2;
                    break;
                case STATUS_CHECK_UPLOAD:
                case STATUS_CHECK_QUALIFIED:
                case STATUS_CHECK_RECTIFICATION:
                case STATUS_CHECK_UNQUALIFIED:
                    stepName = 3;
                    break;
                case STATUS_CERTIFICATE_REPORT_UPLOAD:
                case STATUS_CERTIFICATE_REPORT_QUALIFIED:
                case STATUS_CERTIFICATE_REPORT_UNQUALIFIED:
                    stepName = 4;
                    break;
                default:
                    stepName = -1;
                    break;
            }
            return stepName;
        }


        /**
         * 判断年检状态是否处于其他阶段之间 min < middle < max
         * @param middle 中间值
         * @param min 最小值
         * @param max 最大值
         * @return boolean
         */
        static boolean inStatus(int min, int middle, int max){
            return min <= middle && middle <= max;
        }

        /**
         * 判断两个年检状态是否一样 one == two
         * @param one 一个值
         * @param other 另一个值
         * @return boolean
         */
        static boolean sameStatus(int one, int other){
            return one == other;
        }

        /**
         * 判断年检中一个状态是否为另一个状态的下一个状态
         * @param front 前一个值
         * @param behind 后一个值
         * @return boolean
         */
        static boolean nextStatus(int front, int behind){
            return front + 1 == behind;
        }

        /**
         * 判断年检中两个状态相同或者为下一个状态
         * @param front 前一个值
         * @param behind 后一个值
         * @return boolean
         */
        static boolean sameNext(int front, int behind){
            return front == behind || front + 1 == behind;
        }

        //==============================================================================
    }

    interface Repair{
        //===================急修相关状态值和判断方法======================================
        /**
         * 急修状态（-1 暂停中）
         */
        int STATUS_STOPING          = -1;

        static boolean statusStoping(int status){
            return STATUS_STOPING == status;
        }
        /**
         * 急修状态（0 待修理）
         */
        int STATUS_TO_REPAIRED      = 0;

        static boolean statusToRepaired(int status){
            return STATUS_TO_REPAIRED == status;
        }
        /**
         * 急修状态（1 修理中）
         */
        int STATUS_REPAIRING        = 1;

        static boolean statusRepairing(int status){
            return STATUS_REPAIRING == status;
        }
        /**
         * 急修状态（2 完成）
         */
        int STATUS_FINISH           = 2;

        static boolean statusFinish(int status){
            return STATUS_FINISH == status;
        }
        /**
         * 急修状态（3 关闭）
         */
        int STATUS_CLOSE            = 3;
        static boolean statusClose(int status){
            return STATUS_CLOSE == status;
        }
        String haveUnfinisedRepair  = "该电梯存在未完成的急修，无法创建";
        String repairHadTaked       = "急修已经接单，不能转派";
        String mustToRepair         = "待急修才能操作";
        String mustInRepairing      = "急修中才能操作";
        String missingFault         = "缺少故障信息";
        String mustFinish           = "急修完成后才能操作";
        String hadEvaluate          = "急修已经评价了";
        String incorrectAmount      = "金额有误";

        //==============================================================================
    }

    interface Upload{
        //===================上传相关状态值和判断方法======================================
        /**
         * 图片上传最大大小10M * 1024 * 1024
         */
        long maxSizePic             = 10 << 20;
        String maxSizePicDesc       = "10M";
        /**
         * 文件上传最大大小50M * 1024 * 1024
         */
        long maxSizeFile            = 50 << 20;
        String maxSizeFileDesc      = "50M";
        /**
         * 视频上传最大大小100M * 1024 * 1024
         */
        long maxSizeVideo           = 100 << 20;
        String maxSizeVideoDesc     = "100M";

        /**
         * 上传图片文件类型
         */
        String[] pics               = {".jpg",".jpeg", ".png", ".bmp", ".gif"};
        /**
         * 上传其他文件类型
         */
        String[] files              = {".pdf",".txt",".rar",".zip",".7z", ".xls", ".xlsx", ".doc",".docx",".ppt",".pptx"};
        /**
         * 上传视频文件类型
         */
        String[] videos             = {".mov",".mp4", ".avi",".mpg",".mpeg",".rm",".rmvb",".wmv"};


        String fileDataMissing      = "没有文件数据";
        String fileUploadFail       = "上传文件失败";
        String fileFormatNotSupport = "文件格式暂时不支持";
        String fileFormatIllegal    = "文件格式不合法";
        //==============================================================================
    }

    /**
     * 操作证相关常量
     */
    interface LiftCert{
        //0：无证，1：待审核，2：审核未通过，3：审核通过，4：超期
        int Status_Unlicense        = 0;
        int Status_ToAudit          = 1;
        int Status_AuditFail        = 2;
        int Status_AuditPass        = 3;
        int Status_Overdue          = 4;

        String MustToAudit          = "待审核才能操作";
        String CertHadExist         = "操作证已存在";
        String CertNotExist         = "操作证不存在";

        static boolean unlicense(int status){
            return status == Status_Unlicense;
        }
        static boolean toAudit(int status){
            return status == Status_ToAudit;
        }
        static boolean auditFail(int status){
            return status == Status_AuditFail;
        }
        static boolean auditPass(int status){
            return status == Status_AuditPass;
        }
        static boolean overdue(int status){
            return status == Status_Overdue;
        }
    }

    /**
     * 签到相关常量
     */
    interface Attend{
        String SetAmTime            = "请设置上午的上/下班时间";
        String SetPmTime            = "请设置下午的上/下班时间";
        String SetOtTime            = "请设置加班的上/下班时间";
        String InvalidAmTime        = "上午的上/下班时间有误";
        String InvalidPmTime        = "下午的上/下班时间有误";
        String InvalidOtTime        = "加班的上/下班时间有误";
        String AmTopClock           = "上午上班打卡";
        String AmDownClock          = "上午下班打卡";
        String PmTopClock           = "下午上班打卡";
        String PmDownClock          = "下午下班打卡";
        String OtTopClock           = "加班上班打卡";
        String OtDownClock          = "加班下班打卡";
        String hadClock             = "打卡记录已存在";
    }

    interface Excel{
        String ValidDataMissing     = "未解析到有效数据";
        String FormatSupport        = "文件格式不支持，暂时只支持xls,xlsx";
        String[] excelSuffix        = {".xls",".xlsx"};
        /**
         * 一次导入表格的最大有效记录数
         */
        int maxRows                 = 5000;
        String outMaxRows           = "一次性导入不能超过5000条数据";
    }
}
