<?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;

		$isAuthorized = $db->getValue('SELECT myUser_checkRestPriv(#)',
			[$_REQUEST['method']]);
		if (!$isAuthorized)
			throw new ForbiddenException(s('You don\'t have enough privileges'));

		if ($method::SECURITY == Security::DEFINER) {
			$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.myUser_logout');

		$db->query('CALL account.myUser_logout');
		
		return $res;
	}
	
	function statusFromException($e) {
		try {
			throw $e;
		} catch (SessionExpiredException $e) {
			$status = 401;
		} catch (BadLoginException $e) {
			$status = 401;
		} catch (ForbiddenException $e) {
			$status = 403;
		} catch (Lib\UserException $e) {
			$status = 400;
		} catch (\Exception $e) {
			$status = 500;
		}
			
		http_response_code($status);
	}
	
	function errorHandler($errno, $message, $file, $line, $context = NULL) {
		$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;
	}
}