<?php
namespace App\AuthenticateFromLidia\Webservice;

abstract class ApiGeneralAbstract
{
	/**
	 * Proxy server address
	 * @var String
	 */
	private $proxyServerUrl = NULL;

	/**
	 * Default construct of class
	 * @param String $proxyServerUrl
	 * @throws \Exception
	 */
	public function __construct($proxyServerUrl)
	{
		if (!$proxyServerUrl) {
			throw new \Exception(__METHOD__.': `proxyServerUrl` is not configured.');
		}

		$this->proxyServerUrl = $proxyServerUrl;
	}

	/**
	 * Do the actually request
	 * @param String $post
	 */
	protected function request($post)
	{
		// add auth token
		$postData = json_encode($post);

		// request
		$ch = curl_init();
		if (!$ch) {
			throw new \RuntimeException("Cannot initialize curl");
		}

		curl_setopt($ch, CURLOPT_URL,  			$this->proxyServerUrl);
		curl_setopt($ch, CURLOPT_POST, 			1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, 	$postData);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch, CURLOPT_USERAGENT, 	"LIDIA API PHP 2.0");
		$response = curl_exec ($ch);

		// "obfuscate" logged user & pass
		if ($post && $post->productInstanceCode) {
			$post->productInstanceCode = '*****';
		}
		if ($post && $post->productInstancePass) {
			$post->productInstancePass = '*****';
		}

		if (!$response) {
			$errorMessage = curl_error($ch);
			// log request/response
			\Log::getInstance()->error(sprintf("[%s]. Requested operation:%s failed. Error: %s", __METHOD__, $post->operation, $errorMessage), [
				'request' => new \Engine\Logger\Context\Json($post),
			]);

			throw new \RuntimeException("Empty response from LIDIA. Error during connection: ".$errorMessage);
		}

		// log request/response
		$context = ['request' => 		new \Engine\Logger\Context\Json($post)];

		$curlErrorMessage = curl_error($ch);

		if ($curlErrorMessage) {
			\Log::getInstance()->error(sprintf("[%s]. Requested operation:%s. Curl error message: %s", __METHOD__, $post->operation, $curlErrorMessage), $context);
		}
		else {
			\Log::getInstance()->info(sprintf("[%s]. Requested operation:%s.", __METHOD__, $post->operation), $context);
		}

		// close request
		curl_close ($ch);

		return $response;
	}

	/**
	 * Execute operation
	 */
	public function executeOperation(\App\AuthenticateFromLidia\Webservice\GetCredentials\Request $request, \App\AuthenticateFromLidia\Webservice\ResponseAbstract $response)
	{
		// do the actually request
		$str = $this->request($request);
		$responseStdClass = json_decode($str);

		if (!$responseStdClass) {
			throw new \RuntimeException("The response is invalid.");
		}

		// map general response
		$response->setStatus($responseStdClass->status);
		$response->setMessage($responseStdClass->message);
		$this->mapResponse($response, $responseStdClass);
	}

	/**
	 * Map response standard class with a Tina class
	 * @param \stdClass $response
	 */
	abstract protected function mapResponse(\App\AuthenticateFromLidia\Webservice\ResponseAbstract $response, \stdClass $responseStdClass);
}