const system = require("../system");
const uuidv4 = require('uuid/v4');

class IdcardClient {
    constructor() {
        // 加权因子
        this.weight_factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        // 校验码
        this.check_code = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
    }

    async checkIDCard(idcard) {
        if (!idcard) {
            return false;
        }
        idcard = idcard.toUpperCase();
        var code = idcard.toString().toUpperCase();
        var last = idcard[17];//最后一个

        var seventeen = code.substring(0, 17);

        // ISO 7064:1983.MOD 11-2
        // 判断最后一位校验码是否正确
        var arr = seventeen.split("");
        var len = arr.length;
        var num = 0;
        for (var i = 0; i < len; i++) {
            num = num + arr[i] * this.weight_factor[i];
        }

        // 获取余数
        var resisue = num % 11;
        var last_no = this.check_code[resisue];

        // 格式的正则
        // 正则思路
        /*
        第一位不可能是0
        第二位到第六位可以是0-9
        第七位到第十位是年份，所以七八位为19或者20
        十一位和十二位是月份，这两位是01-12之间的数值
        十三位和十四位是日期，是从01-31之间的数值
        十五，十六，十七都是数字0-9
        十八位可能是数字0-9，也可能是X
        */
        var idcard_patter = /^[1-9][0-9]{5}([1][9][0-9]{2}|[2][0][0|1][0-9])([0][1-9]|[1][0|1|2])([0][1-9]|[1|2][0-9]|[3][0|1])[0-9]{3}([0-9]|[X])$/;

        // 判断格式是否正确
        var format = idcard_patter.test(idcard);

        // 返回验证结果，校验码和格式同时正确才算是合法的身份证号码
        return last === last_no && format ? true : false;
    }

    // async checkIDCard(idCard) {
    //     //15位和18位身份证号码的正则表达式
    //     var regIdCard = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;
    //     //如果通过该验证，说明身份证格式正确，但准确性还需计算
    //     if (regIdCard.test(idCard)) {
    //         if (idCard.length == 18) {
    //             var idCardWi = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //将前17位加权因子保存在数组里
    //             var idCardY = new Array(1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2); //这是除以11后，可能产生的11位余数、验证码，也保存成数组
    //             var idCardWiSum = 0; //用来保存前17位各自乖以加权因子后的总和
    //             for (var i = 0; i < 17; i++) {
    //                 idCardWiSum += idCard.substring(i, i + 1) * idCardWi[i];
    //             }
    //             var idCardMod = idCardWiSum % 11;//计算出校验码所在数组的位置
    //             var idCardLast = idCard.substring(17);//得到最后一位身份证号码
    //             //如果等于2，则说明校验码是10，身份证号码最后一位应该是X
    //             if (idCardMod == 2) {
    //                 if (idCardLast == "X" || idCardLast == "x") {
    //                     return true;
    //                 } else {
    //                     return false;
    //                 }
    //             } else {
    //                 //用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
    //                 if (idCardLast == idCardY[idCardMod]) {
    //                     return true;
    //                 } else {
    //                     return false;
    //                 }
    //             }
    //         }
    //     } else {
    //         return false;
    //     }
    // }

    /**
     *
     * @param card
     * @returns {
     *   birth  生日
     *   sex 性别
     *
     * }
     */
    async cardInfo(card) {
        let info = {};
        //获取出生日期
        info.birth = card.substring(6, 10) + "-" + card.substring(10, 12) + "-" + card.substring(12, 14);
        //获取性别
        if (parseInt(card.substr(16, 1)) % 2 == 1) {
            info.sex = "male";
        } else {
            info.sex = "female";
        }

        //获取年龄
        let myDate = new Date();
        let month = myDate.getMonth() + 1;
        let day = myDate.getDate();
        let age = Number(myDate.getFullYear()) - Number(card.substring(6, 10)) - 1;
        if (card.substring(10, 12) < month || card.substring(10, 12) == month && card.substring(12, 14) <= day) {
            age++;
        }
        info.age = Number(age);
        return info;
    }


    /*

             * 身份证15位编码规则：dddddd yymmdd xx p

             * dddddd：6位地区编码

             * yymmdd: 出生年(两位年)月日，如：910215

             * xx: 顺序编码，系统产生，无法确定

             * p: 性别，奇数为男，偶数为女

             *

             * 身份证18位编码规则：dddddd yyyymmdd xxx y

             * dddddd：6位地区编码

             * yyyymmdd: 出生年(四位年)月日，如：19910215

             * xxx：顺序编码，系统产生，无法确定，奇数为男，偶数为女

             * y: 校验码，该位数值可通过前17位计算获得

             *

             * 前17位号码加权因子为 Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]

             * 验证位 Y = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]

             * 如果验证码恰好是10，为了保证身份证是十八位，那么第十八位将用X来代替

             * 校验位计算公式：Y_P = mod( ∑(Ai×Wi),11 )

             * i为身份证号码1...17 位; Y_P为校验码Y所在校验码数组位置

            */

    async validateIdCard(idCard) {
        //15位和18位身份证号码的正则表达式
        var regIdCard = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;
        //如果通过该验证，说明身份证格式正确，但准确性还需计算
        if (regIdCard.test(idCard)) {
            if (idCard.length == 18) {
                var idCardWi = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //将前17位加权因子保存在数组里
                var idCardY = new Array(1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2); //这是除以11后，可能产生的11位余数、验证码，也保存成数组
                var idCardWiSum = 0; //用来保存前17位各自乖以加权因子后的总和
                for (var i = 0; i < 17; i++) {
                    idCardWiSum += idCard.substring(i, i + 1) * idCardWi[i];
                }
                var idCardMod = idCardWiSum % 11;//计算出校验码所在数组的位置
                var idCardLast = idCard.substring(17);//得到最后一位身份证号码
                //如果等于2，则说明校验码是10，身份证号码最后一位应该是X
                if (idCardMod == 2) {
                    if (idCardLast == "X" || idCardLast == "x") {
                        return "恭喜通过验证啦！";
                    } else {
                        return "身份证号码错误！";
                    }
                } else {
                    //用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
                    if (idCardLast == idCardY[idCardMod]) {
                        return "恭喜通过验证啦！";
                    } else {
                        return "身份证号码错误！";
                    }
                }
            }
        } else {
            return "身份证格式不正确!";
        }
    }


    async isHKCard(card) {
        // 港澳居民来往内地通行证
        // 规则： H/M + 10位或6位数字
        // 样本： H1234567890
        var reg = /^([A-Z]\d{6,10}(\(\w{1}\))?)$/;
        if (reg.test(card) === false) {
            return false;
        } else {
            return true;
        }
    }


    async isPassPortCard(card) {
        // 护照
        // 规则： 14/15开头 + 7位数字, G + 8位数字, P + 7位数字, S/D + 7或8位数字,等
        // 样本： 141234567, G12345678, P1234567
        var reg = /^([a-zA-z]|[0-9]){5,17}$/;
        if (reg.test(card) === false) {
            return false;
        } else {
            return true;
        }
    }

    async isTWCard(card) {
        // 台湾居民来往大陆通行证
        // 规则： 新版8位或18位数字， 旧版10位数字 + 英文字母
        // 样本： 12345678 或 1234567890B
        var reg = /^\d{8}|^[a-zA-Z0-9]{10}|^\d{18}$/;
        if (reg.test(card) === false) {
            return false;
        } else {
            return true;
        }
    }


    async isAccountCard(card) {
        // 户口本
        // 规则： 15位数字, 18位数字, 17位数字 + X
        // 样本： 441421999707223115
        var reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
        if (reg.test(card) === false) {
            return {'status': 0, 'msg': '户口本号码不合规'};
        } else {
            return {'status': 1, 'msg': '校验通过'};
        }
    }

    async isOfficerCard(card) {
        // 军官证
        // 规则： 军/兵/士/文/职/广/（其他中文） + "字第" + 4到8位字母或数字 + "号"
        // 样本： 军字第2001988号, 士字第P011816X号
        var reg = /^[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)$/;
        if (reg.test(card) === false) {
            return {'status': 0, 'msg': '军官证号不合规'};
        } else {
            return {'status': 1, 'msg': '校验通过'};
        }
    }


}

module.exports = IdcardClient;
