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

namespace Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\UserPermission;

use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Credentials;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Configuration;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\Application;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\ApplicationRole;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\User;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\UserApplicationRole;
use Symfony\Bundle\FrameworkBundle\Client;

/**
 * Class Add
 *
 * @copyright  2017 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\UserApplicationRole
 */
class Add
{
    /**
     * @var Configuration
     */
    private $configuration;

    /**
     * @var Client
     */
    private $client;

    /**
     * Add constructor.
     * @param Configuration $configuration
     * @param Client $client
     */
    public function __construct(Configuration $configuration, Client $client)
    {
        $this->configuration = $configuration;
        $this->client = $client;
    }

    /**
     * @param Application $application
     */
    public function execute(Application $application)
    {
        $user = new User();
        $user->setUsername($this->configuration->getUsername());

        $userApplication = new Application();
        $userApplication->setName('WebserviceConsumer');
        $userApplication->setActive(true);
        $userApplication->setDescription('WebserviceConsumer');

        $roleRead = $this->addApplicationRole($userApplication, $application, 'read');
        $roleWrite = $this->addApplicationRole($userApplication, $application, 'write');

        $this->addUserApplicationRole($user, $userApplication, $roleRead);
        $this->addUserApplicationRole($user, $userApplication, $roleWrite);
    }

    /**
     * @param Application $userApplication
     * @param Application $application
     * @param string $permission ["read"|"write"]
     * @return ApplicationRole
     */
    private function addApplicationRole(Application $userApplication, Application $application, $permission)
    {
        $applicationRole = new ApplicationRole();
        $applicationRole->setName($application->getName() . ':' . $permission);

        $this->client->request(
            'POST',
            $this->configuration->getUrlUserWs(),
            [],
            [],
            [
                'HTTP_API-CONTROLLER' => 'ApplicationRole',
                'HTTP_API-ACTION' => 'Add',
                'CONTENT-TYPE' => 'text/xml; charset=UTF-8',
                'HTTP_API-VERSION' => '2',
                'HTTP_REMOTE_ADDR' => '127.0.0.1',
            ],
            $this->getRoleAddRequest($userApplication, $applicationRole)
        );

        return $applicationRole;
    }

    /**
     * @param User $user
     * @param Application $application
     * @param ApplicationRole $role
     * @return UserApplicationRole
     */
    public function addUserApplicationRole(User $user, Application $application, ApplicationRole $role)
    {
        $userApplicationRole = new UserApplicationRole($user, $application, $role);
        $this->client->request(
            'POST',
            $this->configuration->getUrlUserWs(),
            [],
            [],
            [
                'HTTP_API-CONTROLLER' => 'UserApplicationRole',
                'HTTP_API-ACTION' => 'Add',
                'CONTENT-TYPE' => 'text/xml; charset=UTF-8',
                'HTTP_API-VERSION' => '2',
                'HTTP_REMOTE_ADDR' => '127.0.0.1',
            ],
            $this->getUserRoleAddRequest($userApplicationRole)
        );

        return $userApplicationRole;
    }

    /**
     * @param UserApplicationRole $userApplicationRole
     * @return string
     */
    private function getUserRoleAddRequest(UserApplicationRole $userApplicationRole)
    {
        return '<?xml version="1.0" encoding="UTF-8"?>
<SsoRequest>' . (string)(new Credentials($this->configuration)) . '
    <UserApplicationRole>
        <Add>
            <Key>
                <UserType>
                    <Username>' . $this->cdata($userApplicationRole->getUser()->getUsername()) . '</Username>
                </UserType>
                <ApplicationType>
                    <Name>' . $this->cdata($userApplicationRole->getApplication()->getName()) . '</Name>
                </ApplicationType>
            </Key>
            <Value>
                <RoleType>
                    <Name>' . $this->cdata($userApplicationRole->getRole()->getName()) . '</Name>
                </RoleType>
            </Value>
        </Add>
    </UserApplicationRole>
</SsoRequest>';
    }

    /**
     * @param Application $application
     * @param ApplicationRole $applicationRole
     * @return string
     */
    private function getRoleAddRequest(Application $application, ApplicationRole $applicationRole)
    {
        return '<?xml version="1.0" encoding="UTF-8"?>
<SsoRequest>' . (string)(new Credentials($this->configuration)) . '
    <ApplicationRole>
        <Add>
            <Key>
                <ApplicationType>
                    <Name>' . $this->cdata($application->getName()) . '</Name>
                </ApplicationType>
            </Key>
            <Value>
                <RoleType>
                    <Name>' . $this->cdata($applicationRole->getName()) . '</Name>
                    <Description>' . $this->cdata($applicationRole->getDescription()) . '</Description>
                </RoleType>
            </Value>
        </Add>
    </ApplicationRole>
</SsoRequest>';
    }

    /**
     * @param string $value
     * @return string
     */
    protected function cdata($value)
    {
        return '<![CDATA[' . $value . ']]>';
    }
}
