<?php namespace Intellex\Pixabay\Api;

use Intellex\Pixabay\Data\Page;

/**
 * Abstraction of the Pixabay API.
 * @class
 */
abstract class ApiAbstract {

	/** @const string The endpoint which is targeted. */
	const ENDPOINT = 'https://pixabay.com/api/';

	/** @var string The API key used to idetify on Pixabay. */
	private $apiKey;

	/**
	 * Initailize the search.
	 *
	 * @param string The API key used to idetify on Pixabay.
	 */
	public function __construct($apiKey) {
		$this->apiKey = $apiKey;
	}

	/**
	 * Fetch from the API.
	 *
	 * @params array $params The list of GET params to use.
	 *
	 * @return Page The full response from the server.
	 */
	public function fetch($params = []) {

		# Set the params
		$params['key'] = $this->apiKey;
		$params = $this->modifyParams($params);

		# Set the url
		$url = static::ENDPOINT . $this->apiPrefix();

		# Execute
		list($response, $headers, $body) = $this->execute($url, $params);

		# Return response
		return new Page(json_decode($body), $this->usedClassName());
	}

	/**
	 * Execute a CURL on an URL.
	 *
	 * @param string $url The url to read from.
	 * @param array $parameters The GET parameters for the request.
	 *
	 * @return array First element containing headers, second the body of the response.
	 */
	private function execute($url, $parameters) {

		# Set the options
		$options = array(
			CURLOPT_HEADER			=> 1,
			CURLOPT_URL				=> $url . '?' . http_build_query($parameters),
			CURLOPT_FRESH_CONNECT	=> 1,
			CURLOPT_RETURNTRANSFER	=> 1,
			CURLOPT_FORBID_REUSE	=> 1,
			CURLOPT_TIMEOUT			=> 4
		);

		# Initialize
		$curl = curl_init();
		curl_setopt_array($curl, $options);

		# Load
		list($headerBlock, $body) = preg_split('~\r?\n\r?\n~', curl_exec($curl), 2);
		curl_close($curl);

		# Split headers
		$headers = [];
		foreach(preg_split("~\r\n?~", $headerBlock) as $i => $header) {

			# First header
			if(!$i) {
				$response = $header;

			} else {
				list($key, $value) = explode(':', $header);
				$headers[trim($key)] = trim($value);
			}
		}

		return [ $response, $headers, $body ];
	}

	/**
	 * Defines a prefix used for creating a final URL.
	 *
	 * @return string The prefix to append to
	 */
	abstract protected function apiPrefix();

	/**
	 * Additionally modify the parameters.
	 *
	 * @params array $params The current parameters.
	 *
	 * @return array The modified list of parameters.
	 */
	abstract protected function modifyParams($params);

	/**
	 * Define the content of hits.
	 *
	 * @return string The class name of the content.
	 */
	abstract protected function usedClassName();

}
