/**
  * 
  * requests an access token from the authorization server
  * 
  * The client obtains an access token from the authorization server by
  * making an HTTP "POST" request to the token endpoint. The client
  * constructs a request URI by adding the following parameters to the
  * request:
  *
  * - type REQUIRED (The type of user delegation authorization flow)
  *
  * - client_id REQUIRED (The client identifier)
  *
  * - client_secret REQUIRED (The matching client secret)
  *
  * - code REQUIRED (The verification code received from the authorization server)
  *
  * - redirect_uri REQUIRED (The redirection URI used in the initial request)
  *
  * - secret_type OPTIONAL (The access token secret type. If omitted, the authorization
  * server will issue a bearer token (an access token without a matching secret))
  * 
  * @param string $verificationCode
  * @param string $oauthEndpoint
  * @param string $callbackUrl
  * @param string $clientId
  * @param string $clientSecret
  * @param string $type
  * @param string $secretTtype
  * @param string $accessTokenUri
  * @return array
  * @throws Chrisweb_Oauth2_Exception
  */
 public function requestAccessToken($verificationCode = null, $oauthEndpoint = null, $callbackUrl = null, $clientId = null, $clientSecret = null, $grantType = null, $accessTokenUri = null)
 {
     if (is_null($verificationCode)) {
         $verificationCode = $this->getVerificationCode();
     }
     if (is_null($oauthEndpoint)) {
         $oauthEndpoint = $this->_config->getOauthEndpoint();
     }
     if (is_null($callbackUrl)) {
         $callbackUrl = $this->_config->getCallbackUrl();
     }
     if (is_null($clientId)) {
         $clientId = $this->_config->getClientId();
     }
     if (is_null($clientSecret)) {
         $clientSecret = $this->_config->getClientSecret();
     }
     if (is_null($grantType)) {
         $grantType = $this->_config->getGrantType();
     }
     if (is_null(self::$_localHttpClient)) {
         $this->setLocalHttpClient($this->getLocalHttpClient());
     }
     if (is_null($accessTokenUri)) {
         $accessTokenUri = $this->_config->getAccessTokenUri();
     }
     $requiredValuesArray = array('verificationCode', 'clientId', 'clientSecret', 'callbackUrl', 'accessTokenUri', 'oauthEndpoint');
     // throw exception if one of the required values is missing
     foreach ($requiredValuesArray as $requiredValue) {
         if (is_null(${$requiredValue})) {
             require_once 'Chrisweb/Oauth2/Exception.php';
             throw new Chrisweb_Oauth2_Exception('value ' . $requiredValue . ' is empty, pass the ' . ucfirst($requiredValue) . ' as parameter when calling the ' . __METHOD__ . ' method or add it to the options array you pass when creating an instance of the ' . get_class($this) . ' class');
         }
     }
     if (substr($oauthEndpoint, -1) == '/') {
         $oauthEndpoint = substr($oauthEndpoint, 0, strlen($oauthEndpoint) - 1);
     }
     $postParametersArray = array('client_id' => $clientId, 'client_secret' => $clientSecret, 'code' => $verificationCode, 'redirect_uri' => $callbackUrl);
     if (!empty($grantType) && !is_null($grantType)) {
         $postParametersArray['grant_type'] = $grantType;
     }
     self::$_localHttpClient->resetParameters()->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8')->setUri($oauthEndpoint . $accessTokenUri)->setParameterPost($postParametersArray);
     //Zend_Debug::dump(self::$_localHttpClient->getUri());
     //exit;
     $response = self::$_localHttpClient->request('POST');
     if (!is_null($response)) {
         $body = $response->getBody();
         $status = $response->getStatus();
     } else {
         require_once 'Chrisweb/Oauth2/Exception.php';
         throw new Chrisweb_Oauth2_Exception('the response we recieved is emtpy');
     }
     //Zend_Debug::dump($body, 'body');
     //exit;
     if ($status != '200') {
         $errorArray = Zend_Json::decode($body);
         //Zend_Debug::dump($errorArray);
         //exit;
         $errorMessage = '';
         $errorMessage .= 'we recieved an error (' . $status . ') as response';
         if (array_key_exists('error', $errorArray)) {
             if (is_array($errorArray['error'])) {
                 foreach ($errorArray['error'] as $errorKey => $errorValue) {
                     $errorMessage .= ', ' . $errorKey . ': ' . $errorValue;
                 }
             } else {
                 if (is_string($errorArray['error'])) {
                     $errorMessage .= ', error message: ' . $errorArray['error'];
                 }
             }
         }
         if (array_key_exists('error_description', $errorArray)) {
             $errorMessage .= ', description: ' . $errorArray['error_description'];
         }
         if (array_key_exists('error_uri', $errorArray)) {
             $errorMessage .= ', error uri: ' . $errorArray['error_uri'];
         }
         require_once 'Chrisweb/Oauth2/Exception.php';
         throw new Chrisweb_Oauth2_Exception($errorMessage);
     } else {
         $oauthResponse = array();
         // is it a json string or just a string
         try {
             $oauthResponse = Zend_Json::decode($body);
         } catch (Exception $e) {
             // not a json string
             $explodedBody = explode('&', $body);
             //Zend_Debug::dump($explodedBody, '$explodedBody');
             //exit;
             if (count($explodedBody) > 1) {
                 foreach ($explodedBody as $explodedBodyPart) {
                     $responseParts = explode('=', $explodedBodyPart);
                     switch ($responseParts[0]) {
                         case 'access_token':
                             $oauthResponse['access_token'] = $responseParts[1];
                             break;
                         case 'expires':
                             $oauthResponse['expires'] = $responseParts[1];
                             break;
                     }
                 }
             }
         }
     }
     return $oauthResponse;
 }
 /**
  *
  * requests an access token from the authorization server
  * 
  * The client obtains an access token from the authorization server by
  * making an HTTP "POST" request to the token endpoint. The client
  * constructs a request URI by adding the following parameters to the
  * request:
  *
  * - type REQUIRED (The type of user delegation authorization flow)
  *
  * - client_id REQUIRED (The client identifier)
  *
  * - client_secret REQUIRED (The matching client secret)
  *
  * - code REQUIRED (The verification code received from the authorization server)
  *
  * - redirect_uri REQUIRED (The redirection URI used in the initial request)
  *
  * - secret_type OPTIONAL (The access token secret type. If omitted, the authorization
  * server will issue a bearer token (an access token without a matching secret))
  * 
  * @param string $verificationCode
  * @return string
  */
 public function requestAccessToken($verificationCode = null, $siteUrl = null, $callbackUrl = null, $clientId = null, $clientSecret = null, $type = null, $secretTtype = null)
 {
     if (is_null($verificationCode)) {
         $verificationCode = $this->getVerificationCode();
     }
     if (is_null($siteUrl)) {
         $siteUrl = $this->_config->getSiteUrl();
     }
     if (is_null($callbackUrl)) {
         $callbackUrl = $this->_config->getCallbackUrl();
     }
     if (is_null($clientId)) {
         $clientId = $this->_config->getClientId();
     }
     if (is_null($clientSecret)) {
         $clientSecret = $this->_config->getClientSecret();
     }
     if (is_null($type)) {
         $type = $this->_config->getType();
     }
     if (is_null($secretTtype)) {
         $secretTtype = $this->_config->getSecretType();
     }
     if (is_null(self::$_localHttpClient)) {
         $this->setLocalHttpClient($this->getLocalHttpClient());
     }
     $requiredValuesArray = array('verificationCode', 'type', 'clientId', 'clientSecret', 'callbackUrl');
     // throw exception if one of the required values is missing
     foreach ($requiredValuesArray as $requiredValue) {
         if (is_null(${$requiredValue})) {
             require_once 'Zend/Oauth2/Exception.php';
             throw new Zend_Oauth2_Exception('value ' . $requiredValue . ' is empty, pass the ' . ucfirst($requiredValue) . ' as parameter when calling the ' . __METHOD__ . ' method or add it to the options array you pass when creating an instance of the ' . get_class($this) . ' class');
         }
     }
     if (substr($siteUrl, -1) == '/') {
         $siteUrl = substr($siteUrl, 0, strlen($siteUrl) - 1);
     }
     self::$_localHttpClient->resetParameters()->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8')->setUri($siteUrl . self::access_token_uri)->setParameterPost(array('type' => $type, 'client_id' => $clientId, 'client_secret' => $clientSecret, 'code' => $verificationCode, 'redirect_uri' => $callbackUrl, 'secret_type' => $secretTtype));
     //Zend_Debug::dump(self::$_localHttpClient->getUri());
     //exit;
     $response = self::$_localHttpClient->request('POST');
     //Zend_Debug::dump($body, 'body');
     //Zend_Debug::dump($status, 'status');
     //exit;
     if (!is_null($response)) {
         $body = $response->getBody();
         $status = $response->getStatus();
     } else {
         require_once 'Zend/Oauth2/Exception.php';
         throw new Zend_Oauth2_Exception('the response we recieved is emtpy');
     }
     //Zend_Debug::dump($body, 'body');
     //exit;
     if ($status != '200') {
         $errorArray = Zend_Json::decode($body);
         require_once 'Zend/Oauth2/Exception.php';
         throw new Zend_Oauth2_Exception('we recieved an error (' . $status . ') as response: ' . $errorArray['error']['type'] . ' => ' . $errorArray['error']['message']);
     }
     $explodedBody = explode('=', $body);
     if ($explodedBody[0] != 'access_token') {
         require_once 'Zend/Oauth2/Exception.php';
         throw new Zend_Oauth2_Exception('WTF?');
     }
     return $explodedBody[1];
 }