<?php

namespace App\Libraries;

class Amazon
{
	private $awsAccessKeyID;
	private $merchantID;
	private $markedplaceID;
	private $awsSecretAccessKey;
	private $mwsAuthToken;
	private $host = "mws.amazonservices.com";

	private $requestMethod = "POST";
	private $apiEndPoint = "/Feeds/2009-01-01";
	private $signature;
	private $headers = array();

	private $requestCount = 0;
	
	public function __construct($awsAccessKeyID,$merchantID,$markedplaceID,$awsSecretAccessKey,$mwsAuthToken,$amazonCountry = "US")
	{
		$this->awsAccessKeyID = config('amazon.access_key_id');
		$this->awsSecretAccessKey = config('amazon.secret_access_key');
		if($amazonCountry != "US" && $amazonCountry != "CA"){
			$this->awsAccessKeyID = config('amazon.access_key_id2');
			$this->awsSecretAccessKey = config('amazon.secret_access_key2');
		}
		$this->merchantID = $merchantID;
		$this->markedplaceID = $markedplaceID;
		$this->mwsAuthToken = $mwsAuthToken;
		$amazonDomains = array(
			"US"=>"com",
			"CA"=>"ca",
			"FR"=>"fr",
			"DE"=>"de",
			"IN"=>"in",
			"IT"=>"it",
			"CN"=>"cn",
			"JP"=>"co.jp",
			"UK"=>"co.uk",
			"MX"=>"com.mx",
			"ES"=>"es",
			"AU"=>"com.au"
		);
		$this->host = "mws.amazonservices.".$amazonDomains[$amazonCountry];
	}

	public function signRequestData($params){
		$url_parts = array();
		foreach(array_keys($params) as $key){
			$url_parts[] = $key."=".str_replace('%7E','~',rawurlencode($params[$key]));
		}
		sort($url_parts);
		$url_string = implode("&",$url_parts);
		$string_to_sign = $this->requestMethod."\n".$this->host."\n".$this->apiEndPoint."\n".$url_string;

		$secretKey = ($this->awsSecretAccessKey) ? $this->awsSecretAccessKey : $this->mwsAuthToken;

		$signature = hash_hmac("sha256",$string_to_sign,$secretKey,true);
		$this->signature = urlencode(base64_encode($signature));
		return $url_string;
	}

	private function getHeaders(){
		$headers = array (
			'Accept: application/xml',
			'Host: '.$this->host
		);
		return $headers;
	}

	private function getFeedHeaders($feedData = ""){
		$contentMD5 = base64_encode(md5(trim($feedData),true));
		$headers = array (
			'Accept: application/xml',
			'Host: '.$this->host,
			'Content-Type: text/xml',
			'Content-MD5 : '.$contentMD5
		);
		return $headers;
	}

	public function checkRequestLimit(){
		if($this->requestCount >= 10){
			sleep(5);
			$this->requestCount = 0;
		}
	}
	
	public function sendHttpRequest($requestURL,$requestMethod = "POST",$requestData = array()){
		
		if(isset($requestData["feedData"])){
			$feedData = trim($requestData["feedData"]);
			unset($requestData["feedData"]);
			$feedHandler = @fopen('php://temp','rw+');
			fwrite($feedHandler,trim($feedData));
			rewind($feedHandler);
		}
		
		$this->checkRequestLimit();
		
		if(isset($requestData["file"])) $headers[] = 'Content-Type: multipart/form-data';

		$curl = curl_init();
		curl_setopt($curl,CURLOPT_URL,$requestURL);
		curl_setopt($curl,CURLOPT_HEADER,0);
		curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
		curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);
		curl_setopt($curl,CURLOPT_HTTPHEADER,$this->headers);
		
		if($requestMethod == "GET"){
			curl_setopt($curl,CURLOPT_CUSTOMREQUEST,"GET");
		}
		else if($requestMethod == "POST"){
			curl_setopt($curl,CURLOPT_POST,1);
		}
		else if($requestMethod == "PUT"){
			curl_setopt($curl,CURLOPT_POST,1);
		}
		else if($requestMethod == "DELETE"){
			curl_setopt($curl,CURLOPT_POST,1);
		}
		
		if($requestData) curl_setopt($curl,CURLOPT_POSTFIELDS,$requestData);
		if((isset($feedHandler)) && ($feedHandler)) curl_setopt($curl,CURLOPT_INFILE,$feedHandler);
		curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);

		$response = array();
		$response["responseData"] = curl_exec($curl);
		$response["response"] = $response["responseData"];
		$response['info'] = curl_getinfo($curl);
		if(curl_error($curl)){
			$response["error"] = curl_error($curl);
		}
		curl_close($curl);
		$this->requestCount++;
		if($response["response"]) $response["response"] = $this->xmlToArray($response["response"]);
		return $response;
	}

	public function submitFeed($feedType = "_POST_PRODUCT_DATA_",$feedData,$feedFile=""){
		if(!$feedData && file_exists($feedFile)) $feedData = file_get_contents($feedFile);
		if(!$feedData) return array("error" => "empty feed data");

		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Feeds/2009-01-01";
		$contentMD5 = base64_encode(md5($feedData,true));
		$this->headers = array('Accept: application/xml','Host: '.$this->host,'Content-Type: multipart/form-data','Content-MD5: '.$contentMD5);

		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'SubmitFeed',
			"FeedType" => $feedType,
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2009-01-01',
			"SignatureMethod" => 'HmacSHA256'
			
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['MarketplaceIdList.Id.1'] = $this->markedplaceID;

		$url_string = $this->signRequestData($requestData);
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod,['feedData' => $feedData]);
		if((isset($response["response"]["SubmitFeedResponse"])) && $response["response"]["SubmitFeedResponse"]) return $response["response"]["SubmitFeedResponse"];
		return $response;
	}


	public function getFeedSubmissionList($feedSubmissionIdList = array(),$feedTypeList = array(),$feedProcessingStatusList = array()){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Feeds/2009-01-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);

		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetFeedSubmissionList',
			"Merchant" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2009-01-01',
			"SignatureMethod" => 'HmacSHA256'
		);		
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		
		$requestData['Marketplace'] = $this->markedplaceID;

		$url_string = $this->signRequestData($requestData);
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;
		
		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		
		if((isset($response["response"]["GetFeedSubmissionListResult"])) && $response["response"]["GetFeedSubmissionListResult"]) return $response["response"];
		return $response;
	}


	public function GetOrder($orderID){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Orders/2013-09-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetOrder',
			"AmazonOrderId.Id.1" => $orderID,
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2013-09-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["GetOrderResult"]))) return $response["response"]["GetOrderResult"];
		return $response["response"];
	}


	public function listOrders($orderData = array()){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Orders/2013-09-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'ListOrders',
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2013-09-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['MarketplaceId.Id.1'] = $this->markedplaceID;
		if($orderData){
			foreach($orderData as $parm => $value){
				$requestData[$parm] = $value;
			}
		}
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["ListOrdersResult"]))) return $response["response"]["ListOrdersResult"];
		return $response["response"];
	}

	public function listOrderItems($order_id = ""){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Orders/2013-09-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'ListOrderItems',
			"SellerId" => $this->merchantID,
			"AmazonOrderId" => $order_id,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2013-09-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["ListOrderItemsResult"]))) return $response["response"]["ListOrderItemsResult"];
		return $response["response"];
	}
	
	public function xmlToArray($xmlContent = ""){
		if(strpos($xmlContent,'>') === false || strpos($xmlContent,'<') === false || strpos($xmlContent,'<?xml') === false){
			return $xmlContent;
		}
		$xmlArray = array();
		if($xmlContent){
			$xmlContent = str_replace("ns2:","",$xmlContent);
			$xmlObj = simplexml_load_string($xmlContent,"SimpleXMLElement",LIBXML_NOCDATA);
			unset($xmlContent);
			$jsonString = json_encode($xmlObj);
			unset($xmlObj);
			$xmlArray = json_decode($jsonString,true);
		}
		return $xmlArray;
	}


	public function requestReport($reportType = "_GET_MERCHANT_LISTINGS_ALL_DATA_"){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Reports/2009-01-01";

		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'RequestReport',
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2009-01-01',
			"SignatureMethod" => 'HmacSHA256',
			"ReportType" => $reportType
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['Marketplace'] = $this->markedplaceID;

		$url_string = $this->signRequestData($requestData);
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["RequestReportResult"])) && $response["response"]["RequestReportResult"]) return $response["response"]["RequestReportResult"];
		return $response;
	}

	public function getReportRequestList($listData = array()){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Reports/2009-01-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetReportRequestList',
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2009-01-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['Marketplace'] = $this->markedplaceID;
		if($listData){
			foreach($listData as $parm => $value){
				$requestData[$parm] = $value;
			}
		}
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["GetReportRequestListResult"]))) return $response["response"]["GetReportRequestListResult"];
		return $response["response"];
	}

	public function getReport($reportID){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Reports/2009-01-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetReport',
			"ReportId" => $reportID,
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2009-01-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['Marketplace'] = $this->markedplaceID;
		
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		return $response["response"];
	}

	public function getMatchingProduct($asin){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Products/2011-10-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetMatchingProduct',
			"ASINList.ASIN.1" => $asin,
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2011-10-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['MarketplaceId'] = $this->markedplaceID;
		
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["GetMatchingProductResult"]))) return $response["response"]["GetMatchingProductResult"];
		return $response["response"];
	}

	public function GetMatchingProductForId($idType,$id){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Products/2011-10-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetMatchingProductForId',
			"IdList.Id.1" => $id,
			"IdType" => $idType,
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2011-10-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['MarketplaceId'] = $this->markedplaceID;
		
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["GetMatchingProductForIdResult"]))) return $response["response"]["GetMatchingProductForIdResult"];
		return $response["response"];
	}

	public function itemLookup($idType,$id){
		$this->requestMethod = "POST";
		$this->apiEndPoint = "/Products/2011-10-01";
		$this->headers = array('Accept: application/xml','Host: '.$this->host);
		$requestData = array(
			"AWSAccessKeyId" =>	$this->awsAccessKeyID,
			"Action" =>	'GetMatchingProductForId',
			"IdList.Id.1" => $id,
			"IdType" => $idType,
			"SellerId" => $this->merchantID,
			"SignatureVersion" => '2',
			"Timestamp" => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
			"Version" => '2011-10-01',
			"SignatureMethod" => 'HmacSHA256'
		);
		if($this->mwsAuthToken) $requestData['MWSAuthToken'] = $this->mwsAuthToken;
		$requestData['MarketplaceId'] = $this->markedplaceID;
		
		$url_string = $this->signRequestData($requestData);		
		$requestURL = "https://".$this->host.$this->apiEndPoint.'?'.$url_string."&Signature=".$this->signature;

		$response = $this->sendHttpRequest($requestURL,$this->requestMethod);
		if((isset($response["response"]["GetMatchingProductForIdResult"]))) return $response["response"]["GetMatchingProductForIdResult"];
		return $response["response"];
	}

}
