<?php declare(strict_types=1);
/**
 * This file is part of the SplendidBear Websites' projects.
 *
 * Copyright (c) 2019 @ www.splendidbear.org
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace App\Repository;

use App\Entity\PlayedGame;
use App\Entity\Step;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\Persistence\ManagerRegistry;
use RuntimeException;

/**
 * Class StepRepository
 *
 * @package  App\Repository
 * @author   Lang <https://www.splendidbear.org>
 * @category Class
 * @license  https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
 * @link     www.splendidbear.org
 * @since    2019. 10. 27.
 *
 * @method Step|null find($id, $lockMode = null, $lockVersion = null)
 * @method Step|null findOneBy(array $criteria, array $orderBy = null)
 * @method Step[]    findAll()
 * @method Step[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class StepRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Step::class);
    }

    public function findMostRecent(PlayedGame $playedGame): ?Step
    {
        try {
            return $this
                ->createQueryBuilder('s')
                ->andWhere('s.playedGame = :game')
                ->setParameter('game', $playedGame)
                ->orderBy('s.created', 'DESC')
                ->setMaxResults(1)
                ->getQuery()
                ->getOneOrNullResult();
        } catch (NonUniqueResultException $e) {
            throw new RuntimeException(
                sprintf(
                    'Expected at most one result for the most recent step of game ID %d, but got multiple.',
                    $playedGame->id,
                ),
                0,
                $e,
            );
        }
    }

    public function findMostRecentForPlayer(PlayedGame $playedGame, string $player): ?Step
    {
        try {
            return $this
                ->createQueryBuilder('s')
                ->andWhere('s.playedGame = :game')
                ->andWhere('s.player = :player')
                ->setParameter('game', $playedGame)
                ->setParameter('player', $player)
                ->orderBy('s.created', 'DESC')
                ->setMaxResults(1)
                ->getQuery()
                ->getOneOrNullResult();
        } catch (NonUniqueResultException $e) {
            throw new RuntimeException(
                'Expected at most one result for the most recent step of player "%s" in game ID %d, but got multiple.',
                0,
                $e,
            );
        }
    }
}
