<?php
namespace App\Services;

class CreditCardValidator
{
    /**
     * Validate credit card number and return card type.
     * Optionally you can validate if it is a specific type.
     *
     * @param string $ccnumber
     * @param string $cardtype
     * @param string $allowTest
     * @return mixed
     */
    public function CreditCard($ccnumber, $cardtype = '', $allowTest = false) {

        // Check for test cc number
        if ($allowTest == false && $ccnumber == '4111111111111111') {
            return false;
        }

        $ccnumber = preg_replace('/[^0-9]/','',$ccnumber);

        $creditcard = array(
                'VISA'      =>	"/^4/",
                'MC'        =>	"/^5[1-5]/",
                'AMEX'      =>	"/^3[47]/",
                'DC'        =>	"/^3(?:0[0-5]|[68])/",
                'DISCOVER'  =>	"/^6(?:011|5)/",
                'JCB'       =>	"/^(?:2131|1800|35\d{3})/",
        );

        if (empty($cardtype)) {
            $match = false;
            foreach ($creditcard as $cardtype=>$pattern) {
                if (preg_match($pattern,$ccnumber) == 1) {
                    $match=true;
                    break;
                }
            }
            if (!$match) {
                return false;
            }
        } elseif (@preg_match($creditcard[strtolower(trim($cardtype))],$ccnumber) == 0) {
            return false;
        }

        $return['valid']    = $this->LuhnCheck($ccnumber);
        $return['ccnum']    = $ccnumber;
        $return['type']     = $cardtype;
        return $return;
    }

    /**
     * Do a modulus 10 (Luhn algorithm) check
     *
     * @param string $ccnum
     * @return boolean
     */
    public function LuhnCheck($ccnum){
        $checksum = 0;
        for ($i=(2-(strlen($ccnum) % 2)); $i<=strlen($ccnum); $i+=2) {
            $checksum += (int)($ccnum[$i-1]);
        }

        // Analyze odd digits in even length strings or even digits in odd length strings.
        for ($i=(strlen($ccnum)% 2) + 1; $i<strlen($ccnum); $i+=2) {
            $digit = (int)($ccnum[$i-1]) * 2;
            if ($digit < 10){
                $checksum += $digit;
            }else{
                $checksum += ($digit-9);
            }
        }

        if (($checksum % 10) == 0) {
            return true;
        }else{
            return false;
        }
    }
}
