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

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

/**
 * This class represents track three of a magnetic strip identification card
 * such as a United States driver's license.
 */
public class IdentificationCardTrackThree {
    /**
     * CDS protocol version number.
     */
    private String cdsVersion;
    /**
     * Jurisdiction version number.
     */
    private String jurisdictionVersion;
    /**
     * Postal code of the card holder.
     */
    private String postalCode;
    /**
     * License class
     */
    private String licenseClass;
    /**
     * License restrictions.
     */
    private String restrictions;
    /**
     * License endorsements.
     */
    private String endorsements;
    /**
     * Card-holder gender.
     */
    private IdentificationSex sex;
    /**
     * Card-holder height.
     */
    private String height;
    /**
     * Card-holder weight.
     */
    private String weight;
    /**
     * Card-holder hair color.
     */
    private String hairColor;
    /**
     * Card-holder eye color.
     */
    private String eyeColor;
    /**
     * Vendor specific discretionary data.
     */
    private String discretionaryData;

    /**
     * This method attempts to parse track three data out of the raw strip
     * string.
     * @param trackData Track data to parse.
     * @return IdentificationCardTrackThree data if possible, null otherwise.
     */
    public static IdentificationCardTrackThree parse(String trackData) {
        Pattern p = Pattern.compile(".*%([0-9]{1})([0-9]{1})([A-Z 0-9]{11})([A-Z 0-9]{2})([A-Z 0-9]{10})([A-Z 0-9]{4})(1|2|M|F)([0-9 ]{3})([0-9 ]{3})([A-Z ]{3})([A-Z ]{3})([^\\?]{0,37})\\?.*");
        Matcher m = p.matcher(trackData);
        if(m.matches()) {
            IdentificationCardTrackThree track = new IdentificationCardTrackThree();
            track.setCdsVersion(m.group(1));
            track.setJurisdictionVersion(m.group(2));
            track.setPostalCode(m.group(3));
            track.setLicenseClass(m.group(4).trim());
            track.setRestrictions(m.group(5).trim());
            track.setEndorsements(m.group(6).trim());
            track.setHeight(m.group(8).trim());
            track.setWeight(m.group(9).trim());
            track.setHairColor(m.group(10).trim());
            track.setEyeColor(m.group(11).trim());
            track.setDiscretionaryData(m.group(12));
            
            char s = m.group(7).charAt(0);
            IdentificationSex sex = (s=='1' || s=='M')?IdentificationSex.MALE:IdentificationSex.FEMALE;
            track.setSex(sex);
            
            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 Three:").append(ln);
        sb.append("         CDS Version: ").append(cdsVersion).append(ln);
        sb.append("Jurisdiction Version: ").append(jurisdictionVersion).append(ln);
        sb.append("         Postal Code: ").append(postalCode).append(ln);
        sb.append("       License Class: ").append(licenseClass).append(ln);
        sb.append("        Restrictions: ").append(restrictions).append(ln);
        sb.append("        Endorsements: ").append(endorsements).append(ln);
        sb.append("                 Sex: ").append(sex).append(ln);
        sb.append("              Height: ").append(height).append(ln);
        sb.append("              Weight: ").append(weight).append(ln);
        sb.append("          Hair Color: ").append(hairColor).append(ln);
        sb.append("           Eye Color: ").append(eyeColor).append(ln);
        sb.append("  Discretionary Data: ").append(discretionaryData).append(ln);
        return sb.toString();
    }
    
    /**
     * Gets the CDS protocol version number.
     * @return the cdsVersion
     */
    public String getCdsVersion() {
        return cdsVersion;
    }

    /**
     * Sets the CDS protocol version number.
     * @param cdsVersion the cdsVersion to set
     */
    private void setCdsVersion(String cdsVersion) {
        this.cdsVersion = cdsVersion;
    }

    /**
     * Gets the jurisdiction version from the card. 
     * @return the jurisdictionVersion
     */
    public String getJurisdictionVersion() {
        return jurisdictionVersion;
    }

    /**
     * Sets the jurisdiction version on the card.
     * @param jurisdictionVersion the jurisdictionVersion to set
     */
    private void setJurisdictionVersion(String jurisdictionVersion) {
        this.jurisdictionVersion = jurisdictionVersion;
    }

    /**
     * Gets the postal code from the card.
     * @return the postalCode
     */
    public String getPostalCode() {
        return postalCode;
    }

    /**
     * Sets the postal code from the card.
     * @param postalCode the postalCode to set
     */
    private void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    /**
     * Gets the license class.
     * @return the licenseClass
     */
    public String getLicenseClass() {
        return licenseClass;
    }

    /**
     * Sets the license class.
     * @param licenseClass the licenseClass to set
     */
    private void setLicenseClass(String licenseClass) {
        this.licenseClass = licenseClass;
    }

    /**
     * Gets the license restrictions.
     * @return the restrictions
     */
    public String getRestrictions() {
        return restrictions;
    }

    /**
     * Sets the license restrictions.
     * @param restrictions the restrictions to set
     */
    private void setRestrictions(String restrictions) {
        this.restrictions = restrictions;
    }

    /**
     * Gets license endorsements.
     * @return the endorsements
     */
    public String getEndorsements() {
        return endorsements;
    }

    /**
     * Sets license endorsements.
     * @param endorsements the endorsements to set
     */
    private void setEndorsements(String endorsements) {
        this.endorsements = endorsements;
    }

    /**
     * Gets card-holder gender.
     * @return the sex
     */
    public IdentificationSex getSex() {
        return sex;
    }

    /**
     * Sets the card-holder gender.
     * @param sex the sex to set
     */
    private void setSex(IdentificationSex sex) {
        this.sex = sex;
    }

    /**
     * Gets the card-holder height
     * @return the height
     */
    public String getHeight() {
        return height;
    }

    /**
     * Sets the card-holder height.
     * @param height the height to set
     */
    private void setHeight(String height) {
        this.height = height;
    }

    /**
     * Gets the card-holder weight.
     * @return the weight
     */
    public String getWeight() {
        return weight;
    }

    /**
     * Sets the card-holder weight.
     * @param weight the weight to set
     */
    private void setWeight(String weight) {
        this.weight = weight;
    }

    /**
     * Gets the card-holder hair color.
     * @return the hairColor
     */
    public String getHairColor() {
        return hairColor;
    }

    /**
     * Sets the card-holder hair color.
     * @param hairColor the hairColor to set
     */
    private void setHairColor(String hairColor) {
        this.hairColor = hairColor;
    }

    /**
     * Gets the card-holder eye color.
     * @return the eyeColor
     */
    public String getEyeColor() {
        return eyeColor;
    }

    /**
     * Sets the card-holder eye color.
     * @param eyeColor the eyeColor to set
     */
    private void setEyeColor(String eyeColor) {
        this.eyeColor = eyeColor;
    }

    /**
     * Gets vendor-specific discretionary data.
     * @return the discretionaryData
     */
    public String getDiscretionaryData() {
        return discretionaryData;
    }

    /**
     * Sets vendor-specific discretionary data.
     * @param discretionaryData the discretionaryData to set
     */
    private void setDiscretionaryData(String discretionaryData) {
        this.discretionaryData = discretionaryData;
    }
}
