/*
 * Copyright 2013 - Scriptel Corporation
 */
package com.scriptel.easyscript;

import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class represents track two of a magnetic strip identification card
 * such as a United States driver's license.
 */
public class IdentificationCardTrackTwo {
    /**
     * Issuer identification number.
     */
    private String issuerNumber;
    /**
     * Document number.
     */
    private String idNumber;
    /**
     * Document Expiration date.
     */
    private Date expiration;
    /**
     * Card-holder Birth date.
     */
    private Date birthDate;
    
    /**
     * This method attempts to parse track two data from a raw magnetic strip
     * string.
     * @param trackData Track data to parse.
     * @return IdentificationCardTrackTwo data if possible, null otherwise.
     */
    public static IdentificationCardTrackTwo parse(String trackData) {
        Pattern p = Pattern.compile(".*;(6[0-9]{5})([0-9]{1,13})=([0-9]{4})([0-9]{8})([0-9]{0,5})=?\\?.*");
        Matcher m = p.matcher(trackData);
        if(m.matches()) {
            IdentificationCardTrackTwo track = new IdentificationCardTrackTwo();
            track.setIssuerNumber(m.group(1));
            track.setIdNumber(m.group(2));
            
            int expYear = 2000 + Integer.parseInt(m.group(3).substring(0,2));
            
            //if the exp date on the card is 04/2014, the last day of April
            //is the last day the card is valid. Since Calendar is 0-based,
            //store expMonth as 1-based (making it May), 
            //and then subtract 1 millisecond to kick
            //the exp date back into April.
            int expMonth = Integer.parseInt(m.group(3).substring(2));
            
            Calendar c = Calendar.getInstance();
            c.set(Calendar.YEAR, expYear);
            c.set(Calendar.MONTH, expMonth);
            c.set(Calendar.DAY_OF_MONTH, 1);
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            c.set(Calendar.MILLISECOND, 0);
            
            c.add(Calendar.MILLISECOND, -1);
            track.setExpiration(c.getTime());
            
            int birthYear = Integer.parseInt(m.group(4).substring(0,4));
            int birthMonth = Integer.parseInt(m.group(4).substring(4,6))-1;
            int birthDay = Integer.parseInt(m.group(4).substring(6));
            c.set(Calendar.YEAR, birthYear);
            c.set(Calendar.MONTH, birthMonth);
            c.set(Calendar.DAY_OF_MONTH, birthDay);
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            c.set(Calendar.MILLISECOND, 0);
            track.setBirthDate(c.getTime());
            
            return track;
        }
        
        return null;
    }
    
    /**
     * Returns this object as a human readable string.
     * @return String containing human readable string.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        String ln = System.getProperty("line.separator");
        sb.append("Identification Card - Track Two:").append(ln);
        sb.append("     Issuer Number: ").append(issuerNumber).append(ln);
        sb.append("         ID Number: ").append(idNumber).append(ln);
        sb.append("        Expiration: ").append(expiration).append(ln);
        sb.append("        Birth Date: ").append(birthDate).append(ln);
        return sb.toString();
    }

    /**
     * Gets the issuer identification number. This can be used to determine
     * which state issued the document.
     * @return the issuerNumber
     */
    public String getIssuerNumber() {
        return issuerNumber;
    }

    /**
     * Sets the issuer identification number.
     * @param issuerNumber the issuerNumber to set
     */
    private void setIssuerNumber(String issuerNumber) {
        this.issuerNumber = issuerNumber;
    }

    /**
     * Gets the identification number of the document.
     * @return the idNumber
     */
    public String getIdNumber() {
        return idNumber;
    }

    /**
     * Sets the identification number of the document.
     * @param idNumber the idNumber to set
     */
    private void setIdNumber(String idNumber) {
        this.idNumber = idNumber;
    }

    /**
     * Gets the expiration date of the document.
     * @return the expiration
     */
    public Date getExpiration() {
        return expiration;
    }

    /**
     * Sets the expiration date of the document.
     * @param expiration the expiration to set
     */
    private void setExpiration(Date expiration) {
        this.expiration = expiration;
    }

    /**
     * Gets the birth date of the card-holder.
     * @return the birthDate
     */
    public Date getBirthDate() {
        return birthDate;
    }

    /**
     * Sets the birth date of the card-holder.
     * @param birthDate the birthDate to set
     */
    private void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
}
