/**
 *  @title: 身份证验证
 *  @date: 2019/11/23
 *  @author:zhaobingfeng
 */
/* 省,直辖市代码表 */
const provinceAndCitys = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外'
}
/* 每位加权因子 */
const powers = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2']
/* 第18位校检码 */
const parityBit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
/* 性别  M 男 F 女 */
const genders = { male: 'M', female: 'F' }
/* 校验地址码 */
const checkAddressCode = addressCode => {
    let check = /^[1-9]\d{5}$/.test(addressCode)
    if (!check) return false
    if (provinceAndCitys[parseInt(addressCode.substring(0, 2))]) {
        return true
    } else {
        return false
    }
}

/* 校验日期码 */
const checkBirthDayCode = birDayCode => {
    let check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode)
    if (!check) return false
    let yyyy = parseInt(birDayCode.substring(0, 4), 10)
    let mm = parseInt(birDayCode.substring(4, 6), 10)
    let dd = parseInt(birDayCode.substring(6), 10)
    let xdata = new Date(yyyy, mm - 1, dd)
    if (xdata > new Date()) {
        return false// 生日不能大于当前日期
    } else if ((xdata.getFullYear() === yyyy) && (xdata.getMonth() === mm - 1) && (xdata.getDate() === dd)) {
        return true
    } else {
        return false
    }
}

/* 计算校检码 */
const getParityBit = idCardNo => {
    let id17 = idCardNo.substring(0, 17)
    /* 加权 */
    let power = 0
    for (let i = 0; i < id17.length; i++) {
        power += parseInt(id17.charAt(i), 10) * parseInt(powers[i])
    }
    /* 取模 */
    let mod = power % 11
    return parityBit[mod]
}

/* 验证校检码 */
const checkParityBit = idCardNo => {
    let parityBit = idCardNo.charAt(idCardNo.length - 1).toUpperCase()
    if (getParityBit(idCardNo) == parityBit) {
        return true
    } else {
        return false
    }
}

// 校验15位的身份证号码
const check15IdCardNo = idCardNo => {
    // 15位身份证号码的基本校验
    let check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo)
    if (!check) return false
    // 校验地址码
    let addressCode = idCardNo.substring(0, 6)
    check = checkAddressCode(addressCode)
    if (!check) return false
    let birDayCode = '19' + idCardNo.substring(6, 12)
    // 校验日期码
    check = checkBirthDayCode(birDayCode)
    if (!check) return false
    // 验证校检码
    return idCardNo.length === 18 ? checkParityBit(idCardNo) : true
}

// 校验18位的身份证号码
const check18IdCardNo = idCardNo => {
    // 18位身份证号码的基本格式校验
    let check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo)
    if (!check) return false
    // 校验地址码
    let addressCode = idCardNo.substring(0, 6)
    check = checkAddressCode(addressCode)
    if (!check) return false
    // 校验日期码
    let birDayCode = idCardNo.substring(6, 14)
    check = checkBirthDayCode(birDayCode)
    if (!check) return false
    // 验证校检码
    return checkParityBit(idCardNo)
}

const formateDateCN = day => {
    let yyyy = day.substring(0, 4)
    let mm = day.substring(4, 6)
    let dd = day.substring(6)
    return yyyy + '-' + mm + '-' + dd
}

/* 18位转15位 */
export function getId15 (idCardNo = '') {
    if (idCardNo.length === 15) {
        return idCardNo
    } else if (idCardNo.length === 18) {
        return idCardNo.substring(0, 6) + idCardNo.substring(8, 17)
    } else {
        return null
    }
}

/* 15位转18位 */
export function getId18 (idCardNo = '') {
    if (idCardNo.length === 15) {
        let id17 = idCardNo.substring(0, 6) + '19' + idCardNo.substring(6)
        let parityBit = getParityBit(id17)
        return id17 + parityBit
    } else if (idCardNo.length === 18) {
        return idCardNo
    } else {
        return null
    }
}

/* 校验15位或18位的身份证号码 */
export function checkIdCardNo (idCardNo = '') {
    // 15位和18位身份证号码的基本校验
    let check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo)
    if (!check) return false
    // 判断长度为15位或18位
    if (idCardNo.length === 15) {
        return check15IdCardNo(idCardNo)
    } else if (idCardNo.length === 18) {
        return check18IdCardNo(idCardNo)
    } else {
        return false
    }
}

// 获取身份证信息
export function getIdCardInfo (idCardNo = '') {
    let idCardInfo = {
        gender: '', // 性别
        birthday: '' // 出生日期(yyyy-mm-dd)
    }
    if (idCardNo.length === 15) {
        let aday = '19' + idCardNo.substring(6, 12)
        idCardInfo.birthday = formateDateCN(aday)
        if (parseInt(idCardNo.charAt(14)) % 2 === 0) {
            idCardInfo.gender = genders.female
        } else {
            idCardInfo.gender = genders.male
        }
    } else if (idCardNo.length === 18) {
        let aday = idCardNo.substring(6, 14)
        idCardInfo.birthday = formateDateCN(aday)
        if (parseInt(idCardNo.charAt(16)) % 2 === 0) {
            idCardInfo.gender = genders.female
        } else {
            idCardInfo.gender = genders.male
        }
    } else {
        return null
    }
    return idCardInfo
}

// 根据身份证号，获取年龄
export function getAgeOfIdCard (idCardNo) {
    let strBirthday = getIdCardInfo(idCardNo).birthday
    let returnAge = 0
    let strBirthdayArr = strBirthday.split('-')
    let birthYear = strBirthdayArr[0]
    let birthMonth = strBirthdayArr[1]
    let birthDay = strBirthdayArr[2]

    let d = new Date()
    let nowYear = d.getFullYear()
    let nowMonth = d.getMonth() + 1
    let nowDay = d.getDate()

    if (nowYear === birthYear) {
        returnAge = 0// 同年 则为0岁
    } else {
        let ageDiff = nowYear - birthYear // 年之差
        if (ageDiff > 0) {
            if (nowMonth === birthMonth) {
                let dayDiff = nowDay - birthDay// 日之差
                if (dayDiff < 0) {
                    returnAge = ageDiff - 1
                } else {
                    returnAge = ageDiff
                }
            } else {
                let monthDiff = nowMonth - birthMonth// 月之差
                if (monthDiff < 0) {
                    returnAge = ageDiff - 1
                } else {
                    returnAge = ageDiff
                }
            }
        } else {
            returnAge = -1 // 返回-1 表示出生日期输入错误 晚于今天
        }
    }
    return returnAge// 返回周岁年龄
}
