<?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  2019 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Sso\WebserviceBundle\Database\Webservice;

use Doctrine\ORM\EntityManagerInterface;
use Sso\WebserviceBundle\Entity\Webservice\Type\UserGroup as ModelUserGroup;
use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\Validator\Validator\LegacyValidator;
use Symfony\Component\Validator\Validator\ValidatorInterface as Validator;

/**
 * Class UserGroupGroup
 *
 * @copyright  2019 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Sso\WebserviceBundle\Database\Webservice
 */
class UserGroup extends Base
{
    /**
     * @var ErrorHandlerInterface
     */
    private $errorHandler;

    /**
     * UserGroup constructor.
     * @param EntityManagerInterface $entityManager
     * @param LegacyValidator|Validator $validator
     * @param boolean $readonly
     */
    public function __construct(EntityManagerInterface $entityManager, Validator $validator, $readonly, ErrorHandlerInterface $errorHandler)
    {
        $this->errorHandler = $errorHandler;
        parent::__construct($entityManager, $validator, $readonly);
    }

    /**
     * Save user
     * @param ModelUserGroup $typeUserGroup
     * @return bool Returns true on success, false on validation failure
     */
    public function saveUserGroup(ModelUserGroup $typeUserGroup)
    {
        $validationGroups = [$typeUserGroup->isPersistent() ? 'UserGroup_Update' : 'UserGroup_Add'];
        if (!$this->validate($typeUserGroup, 'ug100', $validationGroups)) {
            return false;
        }

        if ($this->readonly) {
            return false;
        }

        $this->entityManager->persist($typeUserGroup);
        $this->entityManager->flush($typeUserGroup);

        return true;
    }

    /**
     * Delete userGroup
     * @param ModelUserGroup $typeUserGroup
     * @return bool True on success
     */
    public function deleteUserGroup(ModelUserGroup $typeUserGroup)
    {
        $validationGroups = ['UserGroup_Delete'];
        if (!$this->validate($typeUserGroup, 'ug200', $validationGroups)) {
            return false;
        }

        if ($this->readonly) {
            return false;
        }

        $this->entityManager->remove($typeUserGroup);
        $this->entityManager->flush($typeUserGroup);

        return true;
    }

    /**
     * @param string $name
     * @return ModelUserGroup|null
     */
    public function findByUserGroupName(string $name): ?ModelUserGroup
    {
        return $this->entityManager->getRepository(ModelUserGroup::class)->findOneBy(['lowerName' => strtolower($name)]);
    }

    /**
     * @param int $limit
     * @param int $offset
     * @return ModelUserGroup[]
     */
    public function findAll(int $limit, int $offset): array
    {
        return $this->entityManager->getRepository(ModelUserGroup::class)->findBy([], ['lowerName' => 'ASC'], $limit, $offset);
    }

    /**
     * @return int
     * @throws \Doctrine\ORM\NoResultException
     * @throws \Doctrine\ORM\NonUniqueResultException
     */
    public function countAll(): int
    {
        return $this->entityManager
            ->createQuery('SELECT COUNT(ug) FROM ' . ModelUserGroup::class . ' ug')
            ->getSingleScalarResult();
    }

    /**
     * @return ModelUserGroup
     */
    public function createUserGroup(): ModelUserGroup
    {
        return new ModelUserGroup();
    }

    /**
     * @param object $object
     * @param string $errorRef
     * @param array $validationGroups
     * @return bool
     */
    private function validate($object, string $errorRef, array $validationGroups): bool
    {
        $violations = $this->validator->validate($object, $validationGroups);
        if (0 < count($violations)) {
            foreach ($violations as $violation) {
                /** @var ConstraintViolationInterface $violation */
                $this->errorHandler->addError(
                    $violation->getCode(),
                    $violation->getCode(),
                    $errorRef,
                    $violation->getMessage(),
                    (string)$violation
                );
            }
            return false;
        }

        return true;
    }
}
