<?php
	// namespace
	namespace sven\sys\security;


	use \sven\sys\sven as sven;
	use \sven\sys\mysql\mysql as mysql;
	use \sven\sys\core as CORE;
	use \Lcobucci\JWT\Builder as JWT_Builder;
	use \Lcobucci\JWT\Signer\Hmac\Sha256 as JWT_Sha256;
	use \Lcobucci\JWT\ValidationData as JWT_Validation;
	use \Lcobucci\JWT\Parser as JWT_Parser;

	$dir = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, dirname(__FILE__)."/../sources/jwt/src/");
	if(file_exists($dir)) {
		$files = [
			$dir.'Claim.php', $dir.'Claim\Validatable.php', $dir.'Parser.php', $dir.'Builder.php', $dir.'Signer.php', $dir.'Token.php', $dir.'ValidationData.php', $dir.'Claim\Basic.php', $dir.'Claim\EqualsTo.php', $dir.'Claim\Factory.php', $dir.'Claim\GreaterOrEqualsTo.php', $dir.'Claim\LesserOrEqualsTo.php',
			$dir.'Parsing\Decoder.php', $dir.'Parsing\Encoder.php', $dir.'Signature.php', $dir.'Signer\BaseSigner.php',
			$dir.'Signer\Ecdsa\KeyParser.php', $dir.'Signer\Ecdsa.php', $dir.'Signer\Ecdsa\Sha256.php', $dir.'Signer\Ecdsa\Sha384.php', $dir.'Signer\Ecdsa\Sha512.php',
			$dir.'Signer\Hmac.php', $dir.'Signer\Hmac\Sha256.php', $dir.'Signer\Hmac\Sha384.php', $dir.'Signer\Hmac\Sha512.php',
			$dir.'Signer\Key.php', $dir.'Signer\Keychain.php',
			$dir.'Signer\Rsa.php', $dir.'Signer\Rsa\Sha256.php', $dir.'Signer\Rsa\Sha384.php', $dir.'Signer\Rsa\Sha512.php'
		];

		foreach ($files as $file) {
			if(file_exists($file)) {
				require_once($file);
			} else
				return \sven\sys\core::addException(new \sven\sys\Exception("ERROR: Files not found", "JWT Library was not found ({$file})", 404));
		}
	} else {
		return \sven\sys\core::addException(new \sven\sys\Exception("ERROR: Files not found", "JWT Library was not found", 404));
	}
	unset($dir);

	/**
	 * auth
	 *
	 * Authentication class
	 *
	 * @package sven\sys\security
	 * @copyright 2018 Ruben Meyer
	 * @author Ruben Meyer <contact@rxbn.de>
	 * @version 0.1.0
	 * @TODO Documentation
	 *
	 */
	class auth {

		private const TOKEN_SIGNATURE = "5641189c6596892b8b03a8d939803747";

		public function __construct() {
			$mysql = new mysql();
			$fluent = $mysql->getBuilder();
			if(get_class($fluent) === "sven\sys\sven\uncallable") {
				CORE::addException(new \sven\sys\Exception("\sven\sys\sven\uncallable", "Can't find/use FluentPDO"));
			}
		}

		public function loggedIn() {
			$cookie = new cookie();
			$body = \sven\sys\sven\web::getRequestBody();

			$token = ($cookie->read("JWT_SVEN") ? $cookie->read("JWT_SVEN") : null);
			if($token) {
				if($cookie->read("JWT_SVEN") || $token) {
					$token = (new JWT_Parser())->parse((string) $token);

					$signer = new JWT_Sha256;
					return $token->verify($signer, self::TOKEN_SIGNATURE);
				}
			} else {
				if(isset($user) && isset($pass))
					return $this->verifyLogin($user, $pass);
			}
			return false;
		}

		public function verifyLogin($username, $password) {
			$mysql = new mysql();
			$fluent = $mysql->getBuilder();
			if(get_class($fluent) !== "sven\sys\sven\uncallable") {
				$query = $fluent->from('t_benutzer')->select('t_benutzer.*')->where("Name = ?", $username);
				$data = $query->fetch();

				if($data && $this->verifyPassword($password, $data->Passwort)) {
					return true;
				}
			} else {
				CORE::addException(new \sven\sys\Exception("\sven\sys\sven\uncallable", "Can't find/use FluentPDO"));
			}
			return false;
		}

		public function login($username) {
			$session = new session();
			$session->write('auth_username', $username);
			$session->write('auth_ip', $_SERVER['REMOTE_ADDR']);

			$signer = new JWT_Sha256;

			$time = time();
			$token = (new JWT_Builder())->setIssuer('https://rxbn.de')
									  ->setAudience('http://eps.local')
									  ->setId('4f1g26a1aba', true)
									  ->setIssuedAt($time)
									  ->setNotBefore($time+60)
									  ->setExpiration($time+60*60)
									  ->set('username', $username)
									  ->sign($signer, self::TOKEN_SIGNATURE)
									  ->getToken();

			$cookie = new cookie();
			$cookie->write('JWT_SVEN', (string) $token);
			return (string) $token;
		}

		public function logout() {
			$cookie = new cookie();
			$cookie->drop();
			$session = new session();
			$session->drop();
		}

		public function createCSRF($form_name) {
			$token = bin2hex(random_bytes(32));
			$session = new session();
			$session->write('csrf_form_'.$form_name, $token);
			return $token;
		}

		public function validateCSRF($form_name, $token) {
			$session = new session();
			return hash_equals($session->read('csrf_form_'.$form_name), $token);
		}

		public function hashPassword($password) {
			return password_hash($password, PASSWORD_DEFAULT, ["cost" => 12]);
		}

		public function verifyPassword($password, $hash) {
			return password_verify($password, $hash);
		}

		public function getSomething(){}

	};

?>
