<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace LifeStyle\DH\AttributeGeneratorBundle\Generator\ApplicationAttribute;

use Doctrine\DBAL\DBALException;
use Doctrine\ORM\EntityManager;
use LifeStyle\DH\AttributeGeneratorBundle\Entity\AttributeEmployeeId;
use LifeStyle\DH\AttributeGeneratorBundle\Exception\AttributeNotFoundException;
use Sso\WebserviceBundle\Generator\ApplicationAttribute\GeneratorInterface;

/**
 * Class EmployeeIdGenerator
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package LifeStyle\DH\AttributeGeneratorBundle\Generator\ApplicationAttribute
 */
class EmployeeIdGenerator implements GeneratorInterface
{
    /**
     * @var EntityManager
     */
    private $entityManager;

    /**
     * EmployeeIdGenerator constructor.
     * @param EntityManager $entityManager
     */
    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return 'employeeId';
    }

    /**
     * @return string
     * @throws AttributeNotFoundException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function generate(): string
    {
        $employeeId = $this->getEmployeeId();
        if (null === $employeeId) {
            throw new AttributeNotFoundException('No more employee-ids are available!');
        }

        $repository = $this->entityManager->getRepository(AttributeEmployeeId::class);
        $employeeIdEntity = $repository->find($employeeId);
        $employeeIdAsString = $employeeIdEntity->getEmployeeId();
        $this->entityManager->remove($employeeIdEntity);
        $this->entityManager->flush();

        return $employeeIdAsString;
    }

    /**
     * @return int|null
     * @throws AttributeNotFoundException
     */
    private function getEmployeeId()
    {
        /* Fast random select @see http://jan.kneschke.de/projects/mysql/order-by-rand/ */
        $sql = 'SELECT r1.id FROM dh_attribute_employee_id AS r1 JOIN ' .
            '(SELECT (RAND() * (SELECT MAX(id) FROM dh_attribute_employee_id)) AS id) AS r2 ' .
            'WHERE r1.id >= r2.id ' .
            'ORDER BY r1.id ASC ' .
            'LIMIT 1';

        try {
            $stmt = $this->entityManager->getConnection()->prepare($sql);
            $stmt->execute();
        } catch (DBALException $exception) {
            throw new AttributeNotFoundException();
        }

        $records = $stmt->fetchAll();

        return array_shift($records);
    }
}
