<?php

namespace App\Model;

use App\Model\Entities\Security\User as UserEntity;
use App\Model\Exceptions\Db\RecordNotFoundException;
use App\Model\Facades\UserFacade;
use Nette;
use Nette\Security\AuthenticationException;
use Nette\Security\IAuthenticator;
use Nette\Security\Identity;
use Nette\Security\Passwords;

class Authenticator implements IAuthenticator
{

	/**
	 * @var UserFacade
	 */
	protected $userFacade;

	function __construct(UserFacade $userFacade)
	{
		$this->userFacade = $userFacade;
	}


	/**
	 * Performs an authentication.
	 * @param array $credentials
	 * @return Identity
	 * @throws AuthenticationException
	 */
	public function authenticate(array $credentials)
	{
		if ($credentials[0] instanceof UserEntity) {
			$userEntity = $credentials[0];
		} else {
			$userEntity = $this->authenticateByEmailAndPassword($credentials[0], $credentials[1]);
		}

		return new Identity($userEntity->getId(), null, null);
	}

	protected function authenticateByEmailAndPassword($email, $password) : UserEntity
	{
		try {
			$userCredentials = $this->userFacade->getUserAccountReader()->findCredentialsByEmail($email);
		} catch (RecordNotFoundException $e) {
			throw new AuthenticationException('The e-mail is incorrect.', self::IDENTITY_NOT_FOUND);
		}

		if (!Passwords::verify($password, $userCredentials->getPasswordHash())) {
			throw new AuthenticationException('The password is incorrect.', self::INVALID_CREDENTIAL);
		} elseif (Passwords::needsRehash($userCredentials->getPasswordHash())) {
			$this->userFacade->getUserAccountWriter()->rehashPassword($userCredentials, $password);
		}

		return $userCredentials->getUser();
	}
}
