<?php
/**
 * This file contains the {@link FinancialCard} class.
 * @copyright (c) 2015, Scriptel Corporation.
 */
namespace com\scriptel;

/**
 * This class represents the parsed magnetic strip data from a financial (credit) card.
 * @see <a href="http://en.wikipedia.org/wiki/Magnetic_stripe_card">http://en.wikipedia.org/wiki/Magnetic_stripe_card</a>
 */
class FinancialCard {
    /**
     * Parsed first track from the magnetic strip.
     * @var FinancialCardTrackOne
     */
    private $trackOne;
    /**
     * Parsed second track from the magnetic strip.
     * @var FinancialCardTrackTwo
     */
    private $trackTwo;
    /**
     * Indicates whether or not the parsed card number passes the Luhn checksum algorithm.
     * Used to detect minor errors in card entry.
     * @var boolean
     */
    private $numberValid;
    /**
     * Stores the financial card issuer if it can be identified.
     * @var FinancialCardIssuer
     */
    private $issuer;

    /**
     * This method takes the raw card data from the swipe and attempts to
     * extract financial card data.
     * @param string Raw magnetic strip data.
     * @return \FinancialCard
     */
    public static function parse($cardData) {
        $track1 = FinancialCardTrackOne::parse($cardData);
        $track2 = FinancialCardTrackTwo::parse($cardData);
        if ($track1 != NULL || $track2 != NULL) {
            $card = new FinancialCard;
            $card->setTrackOne($track1);
            $card->setTrackTwo($track2);
            $cardNumber = ($track1 != NULL) ? $track1->getAccountNumber() : $track2->getAccountNumber();
            $card->setIssuer(FinancialCardIssuer::identifyByCardNumber($cardNumber));
            $card->setNumberValid(FinancialCard::verifyCardChecksum($cardNumber));
            return $card;
        }
        return NULL;
    }

    /**
     * Returns this object as a human readable string.
     */
    public function toString() {
        $strCardData = "";
        $strCardData .= "Financial Card \n";
        if ($this->trackOne != NULL) {
            $strCardData .= $this->getTrackOne()->toString() . "\n";
        }
        if ($this->trackTwo != NULL) {
            $strCardData .= $this->getTrackTwo()->toString() . "\n";
        }
        $strCardData .= "Number Valid: " . $this->getNumberValid() . "\n";
        $strCardData .= "      Issuer: " . $this->getIssuer()->getIssuerName() . "\n";
        return $strCardData;
    }
    /**
     * This method takes a card number and applies Luhn's algorithm to verify
     * the card checksum. This method can detect minor transpositions and
     * obviously invalid card numbers, but it cannot detect fake credit card
     * numbers.
     * @param type $cardNumber
     * @return type
     */
    public static function verifyCardChecksum($cardNumber) {
        settype($cardNumber, 'string');
        $table = array(array(0,1,2,3,4,5,6,7,8,9), array(0,2,4,6,8,1,3,5,7,9));
        $sum = 0;
        $flip = 0;
        for ($i = strlen($cardNumber) - 1; $i >= 0; $i--) {
            $sum += $table[$flip++ & 1][$cardNumber[$i]];
        }
        return $sum % 10 === 0;
    }

    /**
     * Gets track one.
     * @return FinancialCardTrackOne Parsed track one.
     */
    function getTrackOne() {
        return $this->trackOne;
    }
    /**
     * Gets track two.
     * @return FinancialCardTrackTwo Parsed track two.
     */
    function getTrackTwo() {
        return $this->trackTwo;
    }
    /**
     * Gets whether or not the credit card number passes Luhn's algorithm.
     * @return boolean.
     */
    function getNumberValid() {
        return $this->numberValid;
    }
    /**
     * Gets the card issuer determined based on card number patterns.
     * @return FianacialCardIssuer the credit card issuer.
     */
    function getIssuer() {
        return $this->issuer;
    }
    /**
     * Sets track one.
     * @param FinancialCardTrackOne $trackOne
     */
    function setTrackOne($trackOne) {
        $this->trackOne = $trackOne;
    }
    /**
     * Sets track two.
     * @param FinancialCardTrackTwo $trackTwo
     */
    function setTrackTwo($trackTwo) {
        $this->trackTwo = $trackTwo;
    }
    /**
     * Sets whether or not the credit card number passes Luhn's algorithm.
     * @param type $numberValid
     */
    function setNumberValid($numberValid) {
        $this->numberValid = $numberValid;
    }
    /**
     * Sets the card issuer.
     * @param FinancialCardIssuer $issuer
     */
    function setIssuer($issuer) {
        $this->issuer = $issuer;
    }


}
