<?php namespace JsonApi;
class Handler {

	private $resource;

	/**
	 * Initialize the handler for a single resource.
	 *
	 * @param	string				$method	The method, as received from the client.
	 * @param	string				$path	The requested path.
	 * @param	string				$data	The supplied data, as array.
	 * @param	ResourceProvider	$data	Provider for supplying the resource.
	 */
	public function __construct($method, $path, $data, Interfaces\ResourceProvider $provider) {

		# On options
		if($method === 'options') {
			$this->executeOptions();
		}

		# Extract request
		$this->request = new Request($method, $path, $data['data']);

		# Get the resource and its id
		$this->resource = $this->loadResource($provider, $this->request);

		# Execute
		switch($this->request->getMethod()) {
			case 'list': $this->executeList(); break;
			case 'get': $this->executeGet($this->request->getId()); break;
			case 'post': $this->executePost($this->request->getData()); break;
			case 'patch': $this->executePatch($this->request->getId(), $this->request->getData()); break;
			case 'delete': $this->executeDelete($this->request->getId()); break;
		}

		# Render JSON
		Response::createSuccess($this->resource)->send();
	}

	private function loadResource(Interfaces\ResourceProvider $provider, Request $request) {
		return $provider->provideResource($request->getType());
	}


	/**
	 * Execute the LIST method (GET method without id in URL).
	 *
	 * @param	$parameters	Additional parameters.
	 */
	public function executeList($parameters = []) {
		$data = $this->resource->executeList($parameters);
		$this->resource->getData()->write($data);
	}

	/**
	 * Execute the GET method.
	 *
	 * @param	$id			The unique id of the resource.
	 * @param	$parameters	Additional parameters.
	 */
	public function executeGet($id, $parameters = []) {
		$data = $this->resource->executeGet($id, $parameters = []);
		if($data === null) {
			throw new \Exception('Resource `' . $this->resource->getType() . '` with id = `' . $id . '` not found.', 404);
		}

		$this->resource->getData()->write($data);
	}

	/**
	 * Execute the POST method.
	 *
	 * @param	$data		The data to update.
	 * @param	$parameters	Additional parameters.
	 */
	public function executePost($data, $parameters = []) {
		$data = $this->resource->executePost($data, $parameters);
		$this->resource->getData()->write($data);
	}

	/**
	 * Execute the PATCH method.
	 *
	 * @param	$id			The unique id of the resource.
	 * @param	$data		The data to update.
	 * @param	$parameters	Additional parameters.
	 */
	public function executePatch($id, $data, $parameters = []) {
		$data = $this->resource->executePatch($data, $parameters);
		$this->resource->getData()->write($data);
	}

	/**
	 * Execute the DELETE method.
	 *
	 * @param	$id			The unique id of the resource.
	 * @param	$parameters	Additional parameters.
	 */
	public function executeDelete($id, $parameters = []) {
		$data = $this->resource->executeDelete($id, $parameters);
		header("HTTP/1.0 204 No Content");
		exit(0);
	}

	public function executeOptions() {
		exit(0);
	}


}
