package com.yanzuoguang.util.sfz;

import com.yanzuoguang.util.exception.ExceptionHelper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 中国居民15位身份证给处理,验证15位身份编码是否合法
 *
 * @author 颜佐光
 */
public class SfzHandle15 implements SfzHandle {

    /**
     * 中国公民身份证号码最小长度。
     */
    public static final int CHINA_ID_MIN_LENGTH = 15;
    /**
     * 最低年限
     */
    public static final int MIN = 1930;

    @Override
    public boolean validate(String idCard) {
        if (idCard.length() != CHINA_ID_MIN_LENGTH) {
            return false;
        }
        if (SfzHandleUtil.isNum(idCard)) {
            String proCode = idCard.substring(0, 2);
            if (SfzHandleUtil.cityCodes.get(proCode) == null) {
                return false;
            }
            String birthCode = idCard.substring(6, 12);
            Date birthDate = null;
            try {
                birthDate = new SimpleDateFormat("yy").parse(birthCode.substring(0, 2));
            } catch (ParseException e) {
                ExceptionHelper.PrintError(SfzHandle15.class, e);
            }
            Calendar cal = Calendar.getInstance();
            if (birthDate != null)
                cal.setTime(birthDate);
            return valiDate(cal.get(Calendar.YEAR),
                    Integer.parseInt(birthCode.substring(2, 4)),
                    Integer.parseInt(birthCode.substring(4, 6))
            );
        } else {
            return false;
        }
    }

    @Override
    public String repair(String idCard) {
        String idCard18 = "";
        if (idCard.length() == SfzHandle18.CHINA_ID_MAX_LENGTH) {
            return idCard;
        }
        if (idCard.length() != CHINA_ID_MIN_LENGTH) {
            return null;
        }
        if (SfzHandleUtil.isNum(idCard)) {
            String birthday = idCard.substring(6, 12);
            String sYear = getBirthDateYear(birthday);
            idCard18 = idCard.substring(0, 6) + sYear + idCard.substring(8);
            // 转换字符数组
            char[] cArr = idCard18.toCharArray();
            if (cArr != null) {
                int[] iCard = SfzHandle18.converCharToInt(cArr);
                int iSum17 = SfzHandle18.getPowerSum(iCard);
                // 获取校验位
                String sVal = SfzHandle18.getCheckCode18(iSum17);
                if (sVal.length() > 0) {
                    idCard18 += sVal;
                } else {
                    return null;
                }
            }
        } else {
            return null;
        }
        return idCard18;
    }

    /**
     * 获取生日年份
     *
     * @param birthday 生日
     * @return 年份
     */
    public static String getBirthDateYear(String birthday) {
        // 获取出生年月日
        Date birthDate = null;
        try {
            birthDate = new SimpleDateFormat("yyMMdd").parse(birthday);
        } catch (ParseException e) {
            ExceptionHelper.PrintError(SfzHandle15.class, e);
        }
        Calendar cal = Calendar.getInstance();
        if (birthDate != null) {
            cal.setTime(birthDate);
        }
        // 获取出生年(完全表现形式,如:2010)
        return String.valueOf(cal.get(Calendar.YEAR));
    }

    @Override
    public String getGender(String idCard) {
        return SfzHandleUtil.SFZ_HANDLE_18.getGender(this.repair(idCard));
    }

    @Override
    public String getBirthday(String idCard) {
        return SfzHandleUtil.SFZ_HANDLE_18.getBirthday(this.repair(idCard));
    }

    @Override
    public String getCountry(String idCard) {
        return SfzHandleUtil.SFZ_HANDLE_18.getCountry(this.repair(idCard));
    }

    @Override
    public String getAreaId(String idCard) {
        return SfzHandleUtil.SFZ_HANDLE_18.getAreaId(this.repair(idCard));
    }

    @Override
    public String getProvinceName(String idCard) {
        return SfzHandleUtil.SFZ_HANDLE_18.getProvinceName(this.repair(idCard));
    }

    /**
     * 验证小于当前日期 是否有效
     *
     * @param iYear  待验证日期(年)
     * @param iMonth 待验证日期(月 1-12)
     * @param iDate  待验证日期(日)
     * @return 是否有效
     */
    public static boolean valiDate(int iYear, int iMonth, int iDate) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int datePerMonth;
        if (iYear < MIN || iYear >= year) {
            return false;
        }
        if (iMonth < 1 || iMonth > 12) {
            return false;
        }
        switch (iMonth) {
            case 4:
            case 6:
            case 9:
            case 11:
                datePerMonth = 30;
                break;
            case 2:
                boolean dm = ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 400 == 0))
                        && (iYear > MIN && iYear < year);
                datePerMonth = dm ? 29 : 28;
                break;
            default:
                datePerMonth = 31;
        }
        return (iDate >= 1) && (iDate <= datePerMonth);
    }
}