/*
 * 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 one of a financial card.
 */
public class FinancialCardTrackOne {
    /**
     * The credit card number of this financial card.
     */
    private String accountNumber;
    /**
     * The first name on the card.
     */
    private String firstName;
    /**
     * The last name on the card.
     */
    private String lastName;
    /**
     * The expiration date on the card.
     */
    private Date expiration;
    /**
     * The service code on the card.
     */
    private String serviceCode;
    /**
     * Optional additional data the issuer has included on the strip.
     */
    private String discretionaryData;
    
    /**
     * This method attempts to parse track one out the raw track string.
     * @param trackData Track data to parse.
     * @return FinancialCardTrackOne data if data found, null otherwise.
     */
    public static FinancialCardTrackOne parse(String trackData) {
        Pattern p = Pattern.compile(".*%[A-Z]{1}(\\d{1,19})\\^([^\\^]{1,30})\\^(\\d{2})(\\d{2})([0-9]{3})([A-Za-z 0-9]*)\\?.*");
        Matcher m = p.matcher(trackData);
        if(m.matches()) {
            FinancialCardTrackOne track = new FinancialCardTrackOne();
            track.setAccountNumber(m.group(1));
            track.setServiceCode(m.group(5));
            track.setDiscretionaryData(m.group(6));
            
            String name = m.group(2);
            int idx = name.indexOf('/');
            if(idx >= 0) {
                track.setLastName(name.substring(0,idx).trim());
                track.setFirstName(name.substring(idx+1).trim());
            } else {
                track.setLastName(name.trim());
                track.setFirstName("");
            }
            
            Calendar c = Calendar.getInstance();
            c.set(Calendar.YEAR, Integer.parseInt(m.group(3))+2000);
            c.set(Calendar.MONTH, Integer.parseInt(m.group(4)));
            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());
            
            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("Financial Card - Track One:").append(ln);
        sb.append("    Account Number: ").append(accountNumber).append(ln);
        sb.append("        First Name: ").append(firstName).append(ln);
        sb.append("         Last Name: ").append(lastName).append(ln);
        sb.append("        Expiration: ").append(expiration).append(ln);
        sb.append("      Service Code: ").append(serviceCode).append(ln);
        sb.append("Discretionary Data: ").append(discretionaryData).append(ln);
        return sb.toString();
    }
    
    /**
     * Gets the account number on the card.
     * @return the accountNumber
     */
    public String getAccountNumber() {
        return accountNumber;
    }

    /**
     * Sets the account number on the card.
     * @param accountNumber Account Number
     */
    private void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }

    /**
     * Gets the first name on the card.
     * @return First Name
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * Sets the first name on the card.
     * @param firstName the firstName to set
     */
    private void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     * Gets the last name on the card.
     * @return Last name
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * Sets the last name one the card.
     * @param lastName Last name.
     */
    private void setLastName(String lastName) {
        this.lastName = lastName;
    }

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

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

    /**
     * Gets the service code on the card.
     * @return Service code.
     */
    public String getServiceCode() {
        return serviceCode;
    }

    /**
     * Sets the service code.
     * @param serviceCode the serviceCode to set
     */
    private void setServiceCode(String serviceCode) {
        this.serviceCode = serviceCode;
    }

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

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