<?php
/**
 * First Data Connect Purchase Request
 */

namespace Omnipay\FirstData\Message;

use Omnipay\Common\Exception\InvalidCreditCardException;
use Omnipay\Common\Message\AbstractRequest;

/**
 * First Data Connect Purchase Request
 */
class PurchaseRequest extends AbstractRequest
{
    protected $liveEndpoint = 'https://www.ipg-online.com/connect/gateway/processing';
    protected $testEndpoint = 'https://test.ipg-online.com/connect/gateway/processing';

    protected function getDateTime()
    {
        return date("Y:m:d-H:i:s");
    }

    /**
     * Set Store ID
     *
     * Calls to the Connect Gateway API are secured with a store ID and
     * shared secret.
     *
     * @return PurchaseRequest provides a fluent interface
     */
    public function setStoreId($value)
    {
        return $this->setParameter('storeId', $value);
    }

    /**
     * Get Store ID
     *
     * Calls to the Connect Gateway API are secured with a store ID and
     * shared secret.
     *
     * @return string
     */
    public function getStoreId()
    {
        return $this->getParameter('storeId');
    }

    /**
     * Set Shared Secret
     *
     * Calls to the Connect Gateway API are secured with a store ID and
     * shared secret.
     *
     * @return PurchaseRequest provides a fluent interface
     */
    public function setSharedSecret($value)
    {
        return $this->setParameter('sharedSecret', $value);
    }

    /**
     * Get Shared Secret
     *
     * Calls to the Connect Gateway API are secured with a store ID and
     * shared secret.
     *
     * @return string
     */
    public function getSharedSecret()
    {
        return $this->getParameter('sharedSecret');
    }

    public function setHostedDataId($value)
    {
        return $this->setParameter('hostedDataId', $value);
    }

    public function getHostedDataId()
    {
        return $this->getParameter('hostedDataId');
    }

    public function setCustomerId($value)
    {
        return $this->setParameter('customerId', $value);
    }

    public function getCustomerId()
    {
        return $this->getParameter('customerId');
    }

    public function getData()
    {
        $this->validate('amount', 'card');

        $data                = array();
        $data['storename']   = $this->getStoreId();
        $data['txntype']     = 'sale';
        $data['timezone']    = 'GMT';
        $data['chargetotal'] = $this->getAmount();
        $data['txndatetime'] = $this->getDateTime();
        $data['hash']        = $this->createHash($data['txndatetime'], $data['chargetotal']);
        $data['currency']    = $this->getCurrencyNumeric();
        $data['mode']        = 'payonly';
        $data['full_bypass'] = 'true';
        $data['oid']         = $this->getParameter('transactionId');

        // If no hosted data, or a number is passed, validate the whole card
        if (is_null($this->getHostedDataId()) || ! is_null($this->getCard()->getNumber())) {
            $this->getCard()->validate();
        } elseif (is_null($this->getCard()->getCvv())) {
            // Else we only require the cvv when using hosted data
            throw new InvalidCreditCardException("The CVV parameter is required when using hosteddataid");
        }

        $data['cardnumber'] = $this->getCard()->getNumber();
        $data['cvm']        = $this->getCard()->getCvv();
        $data['expmonth']   = $this->getCard()->getExpiryDate('m');
        $data['expyear']    = $this->getCard()->getExpiryDate('y');

        $data['bname']    = $this->getCard()->getBillingName();
        $data['baddr1']   = $this->getCard()->getBillingAddress1();
        $data['baddr2']   = $this->getCard()->getBillingAddress2();
        $data['bcity']    = $this->getCard()->getBillingCity();
        $data['bstate']   = $this->getCard()->getBillingState();
        $data['bcountry'] = $this->getCard()->getBillingCountry();
        $data['bzip']     = $this->getCard()->getBillingPostcode();

        $data['sname']    = $this->getCard()->getShippingName();
        $data['saddr1']   = $this->getCard()->getShippingAddress1();
        $data['saddr2']   = $this->getCard()->getShippingAddress2();
        $data['scity']    = $this->getCard()->getShippingCity();
        $data['sstate']   = $this->getCard()->getShippingState();
        $data['scountry'] = $this->getCard()->getShippingCountry();
        $data['szip']     = $this->getCard()->getShippingPostcode();

        $data['phone'] = $this->getCard()->getPhone();
        $data['email'] = $this->getCard()->getEmail();

        $data['responseSuccessURL'] = $this->getParameter('returnUrl');
        $data['responseFailURL']    = $this->getParameter('returnUrl');

        $data['customerid'] = $this->getCustomerId();

        $data['hosteddataid'] = $this->getHostedDataId();

        return $data;
    }

    /**
     * Returns a SHA-1 hash of the transaction data.
     *
     * @param $dateTime
     * @param $amount
     * @return string
     */
    public function createHash($dateTime, $amount)
    {
        $storeId      = $this->getStoreId();
        $sharedSecret = $this->getSharedSecret();
        $currency     = $this->getCurrencyNumeric();
        $stringToHash = $storeId . $dateTime . $amount . $currency . $sharedSecret;
        $ascii        = bin2hex($stringToHash);

        return sha1($ascii);
    }

    public function sendData($data)
    {
        return $this->response = new PurchaseResponse($this, $data);
    }

    public function getEndpoint()
    {
        return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint;
    }
}
