<?php

namespace App\Repository;


use App\Entity\User;
use App\Entity\UserType;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;


class UserTypeRepository extends ServiceEntityRepository
{
    const USER_TYPE_SYSTEM = 'system';
    const USER_TYPE_ADMIN = 'admin';
    const USER_TYPE_USER = 'user';

    const USER_ROLE_SYSTEM = "ROLE_SYSTEM";
    const USER_ROLE_ADMIN = "ROLE_ADMIN";
    const USER_ROLE_USER = "ROLE_USER";

    // Maps user type to set of roles
    private static $userRoles = array(
        self::USER_TYPE_SYSTEM => array(self::USER_ROLE_ADMIN, self::USER_ROLE_SYSTEM),
        self::USER_TYPE_ADMIN => array(self::USER_ROLE_ADMIN, self::USER_ROLE_USER),
        self::USER_TYPE_USER => array(self::USER_ROLE_USER),
    );

    private static $validUserTypes = [
        self::USER_TYPE_SYSTEM, self::USER_TYPE_ADMIN, self::USER_TYPE_USER
    ];

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, UserType::class);
    }

    /**
     * Returns all available user roles
     * @return array
     */
    public static function getAllUserRoles()
    {
        return self::$userRoles;
    }

    /**
     * Returns user roles
     * @param UserType $userType
     * @return string[]
     */
    public static function getUserRoles(UserType $userType)
    {
        return self::$userRoles[$userType->getType()];
    }

    /**
     * Check if a given user type is higher
     *
     * @param UserType $higherUserType
     * @param UserType $lowerUserType
     * @return bool
     */
    public static function isHigherUserType(UserType $higherUserType, UserType $lowerUserType)
    {
        return $higherUserType->getId() < $lowerUserType->getId();
    }

    /**
     * Returns system user
     *
     * @param ObjectManager $em
     * @return object|null
     */
    public static function getSystemUser(ObjectManager $em)
    {
        /** @var UserType $systemUserType */
        $systemUserType = $em->getRepository(UserType::class)->findOneBy(['type' => self::USER_TYPE_SYSTEM]);
        return $em->getRepository(User::class)->findOneBy(['userType' => $systemUserType]);
    }

    /**
     * Return user type by given user type name
     *
     * @param ObjectManager $em
     * @param $userTypeName
     * @return object|null
     * @throws \Exception
     */
    public static function getUserType(ObjectManager $em, $userTypeName)
    {
        if (!in_array($userTypeName, self::$validUserTypes)) {
            throw new \Exception('invalid user type name');
        }
        return $em->getRepository(UserType::class)->findOneBy(['type' => $userTypeName]);
    }

}
