<?php

namespace Omnipay\Coinbase\Message;

/**
 * Coinbase Abstract Request
 *
 * @method \Omnipay\Coinbase\Message\Response send()
 */
abstract class AbstractRequest extends \Omnipay\Common\Message\AbstractRequest {

    protected $endpoint = 'https://api.coinbase.com/v1';

    public function getApiKey() {
        return $this->getParameter('apiKey');
    }

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

    public function getSecret() {
        return $this->getParameter('secret');
    }

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

    public function getAccountId() {
        return $this->getParameter('accountId');
    }

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

    public function sendRequest($method, $action, $data = null) {
        // don't throw exceptions for 4xx errors
        $this->httpClient->getEventDispatcher()->addListener(
                'request.error', function ($event) {
            if ($event['response']->isClientError()) {
                $event->stopPropagation();
            }
        }
        );

        $nonce = $this->generateNonce();
        $url = $this->endpoint . $action;
        $body = $data ? http_build_query($data) : null;

        $httpRequest = $this->httpClient->createRequest($method, $url, null, $body);
        $httpRequest->setHeader('Content-Type', 'application/x-www-form-urlencoded');
        $httpRequest->setHeader('ACCESS_KEY', $this->getApiKey());
        $httpRequest->setHeader('ACCESS_SIGNATURE', $this->generateSignature($url, $body, $nonce));
        $httpRequest->setHeader('ACCESS_NONCE', $nonce);

        return $httpRequest->send();
    }

    public function generateNonce() {
        return sprintf('%0.0f', round(microtime(true) * 1000000));
    }

    public function generateSignature($url, $body, $nonce) {
        $message = $nonce . $url . $body;

        return hash_hmac('sha256', $message, $this->getSecret());
    }

}
