<?php namespace MapGuesser\Repository;

use Generator;
use MapGuesser\Database\Query\Select;
use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\UserInChallenge;
use MapGuesser\PersistentData\PersistentDataManager;

class UserInChallengeRepository
{
    private PersistentDataManager $pdm;

    public function __construct()
    {
        $this->pdm = new PersistentDataManager();
    }

    public function getAllByUser(User $user) : Generator
    {
        $select = new Select(\Container::$dbConnection);
        $select->where('user_id', '=', $user->getId());

        yield from $this->pdm->selectMultipleFromDb($select, UserInChallenge::class);
    }

    public function getAllByChallenge(Challenge $challenge) : Generator
    {
        $select = new Select(\Container::$dbConnection);
        $select->where('challenge_id', '=', $challenge->getId());

        yield from $this->pdm->selectMultipleFromDb($select, UserInChallenge::class);
    }

    public function getAllByChallengeWithUsers(Challenge $challenge) : Generator
    {
        $select = new Select(\Container::$dbConnection);
        $select->where('challenge_id', '=', $challenge->getId());

        yield from $this->pdm->selectMultipleFromDb($select, UserInChallenge::class, true, [User::class]);
    }

    public function getByUserIdAndChallenge(int $userId, Challenge $challenge): ?UserInChallenge
    {
        $select = new Select(\Container::$dbConnection);
        $select->where('user_id', '=', $userId);
        $select->where('challenge_id', '=', $challenge->getId());

        return $this->pdm->selectFromDb($select, UserInChallenge::class);
    }

    public function getByUserIdAndToken(int $userId, string $token_str, array $withRelations = []): ?UserInChallenge
    {
        if (count($withRelations)) {
            $necessaryRelations = [Challenge::class];
            $withRelations = array_unique(array_merge($withRelations, $necessaryRelations));
        }

        // validate token string
        if (!ctype_xdigit($token_str)) {
            return null;
        }
        // convert token to int
        $token = hexdec($token_str);

        $select = new Select(\Container::$dbConnection);
        $select->where('user_id', '=', $userId);
        $select->where('token', '=', $token);

        return $this->pdm->selectFromDb($select, UserInChallenge::class, true, $withRelations);
    }

    public function isUserParticipatingInChallenge(int $userId, Challenge $challenge): bool
    {
        $select = new Select(\Container::$dbConnection, 'user_in_challenge');
        $select->where('user_id', '=', $userId);
        $select->where('challenge_id', '=', $challenge->getId());

        return $select->count() != 0;
    }
}