<?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 Sso\WebserviceBundle\DataFixtures\ORM\Webservice;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Sso\WebserviceBundle\Entity\Webservice\Type\Attribute;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Sso\WebserviceBundle\Entity\Webservice\Type\User;
use Sso\WebserviceBundle\Entity\Webservice\Type\UserApplication;
use Sso\WebserviceBundle\Entity\Webservice\Type\UserApplicationAttribute;
use Sso\WebserviceBundle\Entity\Webservice\Type\UserApplicationRole;
use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
 * Class LoadUserApplications
 * @package Sso\WebserviceBundle\DataFixtures\ORM\Webservice
 */
class LoadUserApplications extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{
    const VALID_SERVICE_TOKEN = 'V2030cOhc6Vttcxs6r6bmtdlc8Z1ryTN1TQ16pjivEcprZhye9e17ba7508a4358f99c8ba52ded0f70RnZDhDyKMXLEWobXI2ZOrJ7mXjcPJJNk7wxoAw8WUTk0IMYa';

    /**
     * @var ContainerInterface
     */
    private $container;

    /**
     * {@inheritDoc}
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /**
     * Creates users
     * - user-api-grant-access
     * - user-api-no-access
     * - user-api-minimal-access
     * @param ObjectManager $manager
     */
    public function load(ObjectManager $manager)
    {
        // Create user without grant api access
        $userEntity = $this->addUser($manager, 'user-api-grant-access');

        // Add application WebserviceConsumer with grant privileges for applications MyNewAppName & WebserviceConsumer
        $userAppEntity = $this->addWebserviceConsumerApplication($manager, $userEntity);
        $this->addWebserviceConsumerGrandPrivileges($manager, $userAppEntity, 'MyNewAppName');
        $this->addWebserviceConsumerGrandPrivileges($manager, $userAppEntity, 'WebserviceConsumer');

        // Add attribute UserWS-ServiceToken
        $this->addWebserviceServiceToken($manager, $userAppEntity);


        // Create user without any api access
        $this->addUser($manager, 'user-api-no-access');


        // Create user with minimal api access
        $this->addUser($manager, 'user-api-minimal-access');
        $userAppEntity = $this->addWebserviceConsumerApplication($manager, $userEntity);
        $this->addWebserviceServiceToken($manager, $userAppEntity);
    }

    /**
     * @param ObjectManager $manager
     * @param string $username
     * @return User
     */
    private function addUser(ObjectManager $manager, $username)
    {
        $passwordCryptDefault = $this->container->get('password_crypt_repository')->getDefault();

        $userEntity = new User($this->getValidator());
        $userEntity->generateId();
        $userEntity->generateGuid();
        $userEntity->setUsername($username);
        $userEntity->setFirstname('PHP');
        $userEntity->setLastname('UNIT');
        $userEntity->setActive(true);
        $userEntity->setPasswordEncryptType($passwordCryptDefault->getEncryptType());
        $userEntity->setPassword('SsO#12Test');
        $userEntity->encryptPassword($passwordCryptDefault);

        $manager->persist($userEntity);
        $manager->flush();

        $this->addReference($username, $userEntity);

        return $userEntity;
    }

    /**
     * @param ObjectManager $manager
     * @param UserApplication $userAppEntity
     * @return UserApplicationAttribute
     */
    private function addWebserviceServiceToken(ObjectManager $manager, UserApplication $userAppEntity)
    {
        $attribute = $this->getReference('application-WebserviceConsumer-attribute-UserWS-ServiceToken');

        $userAppAttribute = new UserApplicationAttribute($this->getValidator());
        $userAppAttribute->generateId();
        $userAppAttribute->setType('many');
        $userAppAttribute->setUserApplication($userAppEntity);
        $userAppAttribute->setValue(static::VALID_SERVICE_TOKEN);
        $userAppAttribute->setAttribute($attribute);

        $manager->persist($userAppAttribute);
        $manager->flush();

        return $userAppAttribute;
    }

    /**
     * @param ObjectManager $manager
     * @param User $userEntity
     * @return UserApplication
     */
    private function addWebserviceConsumerApplication(ObjectManager $manager, User $userEntity)
    {
        $application = $this->getReference('application-WebserviceConsumer');

        $userAppEntity = new UserApplication($this->getValidator());
        $userAppEntity->generateId();
        $userAppEntity->setUser($userEntity);
        $userAppEntity->setApplication($application);
        $userAppEntity->setActive(true);

        $manager->persist($userAppEntity);
        $manager->flush();

        return $userAppEntity;
    }

    /**
     * @param ObjectManager $manager
     * @param UserApplication $userAppEntity
     * @param string $appName
     */
    private function addWebserviceConsumerGrandPrivileges(ObjectManager $manager, UserApplication $userAppEntity, $appName)
    {
        $this->addWebserviceConsumerReadPrivileges($manager, $userAppEntity, $appName);
        $this->addWebserviceConsumerWritePrivileges($manager, $userAppEntity, $appName);
    }

    /**
     * @param ObjectManager $manager
     * @param UserApplication $userAppEntity
     * @param string $appName
     */
    private function addWebserviceConsumerReadPrivileges(ObjectManager $manager, UserApplication $userAppEntity, $appName)
    {
        $this->addWebserviceConsumerPrivileges($manager, $userAppEntity, $appName, 'read');
    }

    /**
     * @param ObjectManager $manager
     * @param UserApplication $userAppEntity
     * @param string $appName
     */
    private function addWebserviceConsumerWritePrivileges(ObjectManager $manager, UserApplication $userAppEntity, $appName)
    {
        $this->addWebserviceConsumerPrivileges($manager, $userAppEntity, $appName, 'write');
    }

    /**
     * @param ObjectManager $manager
     * @param UserApplication $userAppEntity
     * @param string $appName
     * @param string $privilege [read|write]
     */
    private function addWebserviceConsumerPrivileges(ObjectManager $manager, UserApplication $userAppEntity, $appName, $privilege)
    {
        $roleName = $appName . ':' . $privilege;
        $role = $this->getReference('application-WebserviceConsumer-role-' . $roleName);

        $userAppRole = new UserApplicationRole($this->getValidator());
        $userAppRole->generateId();
        $userAppRole->setUserApplication($userAppEntity);
        $userAppRole->setName($roleName);
        $userAppRole->setActive(true);
        $userAppRole->setRole($role);

        $manager->persist($userAppRole);
        $manager->flush();
    }

    /**
     * @return ValidatorInterface
     */
    private function getValidator()
    {
        return $this->container->get('validator');
    }

    /**
     * {@inheritDoc}
     */
    public function getOrder()
    {
        return 2;
    }
}
