<?php

namespace Vn\Web;

use Vn\Lib;
use Vn\Lib\Locale;
use Vn\Lib\UserException;

/**
 * Base class for REST application.
 */
class RestService extends Service
{
	function run ()
	{
		ini_set ('display_errors', _ENABLE_DEBUG);
		set_error_handler ([$this, 'errorHandler'], E_ALL);
		set_exception_handler ([$this, 'exceptionHandler']);

		$this->init ();
		$this->startSession ();
		$this->loadMethod (__NAMESPACE__.'\RestRequest');
	}

	/**
	 * Runs a REST method.
	 */
	function loadMethod ($class)
	{
		$db = $this->db;
		$this->login ();

		$method = $this->app->loadMethod (
			$_REQUEST['method'], $class, './rest');
		$method->service = $this;

		if ($method::SECURITY == Security::DEFINER)
		{
			$isAuthorized = $db->getValue ('SELECT userCheckRestPriv (#)',
				[$_REQUEST['method']]);
	
			if (!$isAuthorized)
				throw new UserException (s('You don\'t have enough privileges'));
			
			$methodDb = $db;
		}
		else
			$methodDb = $this->getUserDb ($_SESSION['user']);

		if ($method::PARAMS !== NULL && !$method->checkParams ($_REQUEST, $method::PARAMS))
			throw new UserException  (s('Missing parameters'));
		
		Locale::addPath ('rest/'. dirname ($_REQUEST['method']));

		$res = NULL;

		try {
			$res = $method->run ($methodDb);
		}
		catch (Db\Exception $e)
		{
			if ($e->getCode () == 1644)
				throw new UserException (s($e->getMessage ()));
		}

		if ($method::SECURITY == Security::DEFINER)
			$methodDb->query ('CALL account.myUserLogout ()');

		$db->query ('CALL account.myUserLogout ()');
		
		return $res;
	}
	
	function statusFromException ($e)
	{
		try {
			throw $e;
		}
		catch (SessionExpiredException $e)
			{ $status = 401; }
		catch (BadLoginException $e)
			{ $status = 401; }
		catch (Lib\UserException $e)
			{ $status = 400; }
		catch (\Exception $e)
			{ $status = 500; }
			
		http_response_code ($status);
	}
	
	function errorHandler ($errno, $message, $file, $line, $context)
	{
		$eFlag =
			  E_USER_NOTICE
			| E_USER_WARNING
			| E_USER_DEPRECATED
			| E_NOTICE
			| E_WARNING
			| E_DEPRECATED;

		if (!($errno & $eFlag))
			http_response_code (500);
		
		return FALSE;
	}

	function exceptionHandler ($e)
	{
		$this->statusFromException ($e);
		throw $e;
	}
}
