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

namespace Sso\DemoBundle\Controller;

use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/**
 * Class UserController
 * @package Sso\DemoBundle\Controller
 */
class UserController extends BaseController
{
    /**
     * @Route("/", name="_sso_demo_user_stress")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function stressAction(Request $request)
    {
        $form = $this->createFormBuilder($this->getFormDefaults())
            ->add($this->buildFormCredentials())
            ->add('apiVersion',
                'choice', [
                    'choices' => [
                        1 => 'Version 1',
                        2 => 'Version 2',
                    ],
                ])
            ->add('UserCount', 'text')
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'Add', 'stressUserAdd');
    }

    /**
     * @Route("/", name="_sso_demo_user_add")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function addAction(Request $request)
    {
        $formDefaults = array_merge($this->getFormDefaults(), [ 'UpdateUserGroups' => true ]);
        $form = $this->createFormBuilder($formDefaults)
            ->add($this->buildFormCredentials())
            ->add('apiVersion',
                'choice', [
                    'choices' => [
                        1 => 'Version 1',
                        2 => 'Version 2',
                        3 => 'Version 3',
                        4 => 'Version 4',
                    ],
                ])
            ->add('Email', 'text', ['required' => false])
            ->add('Username', 'text')
            ->add('Firstname', 'text')
            ->add('Lastname', 'text')
            ->add('Password', 'text')
            ->add('Active', 'text')
            ->add('AuthId', 'text')
            ->add('LdapSearchAttributes', 'text')
            ->add('LdapSearchValue', 'text')
            ->add('MfaEnabled', 'text')
            ->add('PasswordPolicy', 'text')
            ->add('LastPasswordChange', 'datetime',[
                'required' => false
            ])
            ->add('PasswordExpired', 'text')
            ->add('PasswordEncryptType', 'text')
            ->add('UpdateUserGroups', Type\HiddenType::class)
            ->add('UserGroups', Type\CollectionType::class, [
                'block_name' => 'userGroups',
                'entry_type'    => Type\TextType::class,
                'entry_options' => [
                    'label' => false,
                ],
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'required'     => false,
                'attr' => [
                    'class' => 'dynamic-collection',
                ],
            ])
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'Add');
    }

    /**
     * @Route("/", name="_sso_demo_user_show")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function showAction(Request $request)
    {
        $form = $this->createFormBuilder($this->getFormDefaults())
            ->add($this->buildFormCredentials())
            ->add('apiVersion',
                'choice', [
                    'choices' => [
                        1 => 'Version 1',
                        2 => 'Version 2',
                        3 => 'Version 3',
                        4 => 'Version 4',
                        5 => 'Version 5',
                    ],
                ])
            ->add('Guid', 'text')
            ->add('Email', 'text')
            ->add('Username', 'text')
            ->add('Identifier', 'text')
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'Show');
    }

    /**
     * @Route("/", name="_sso_demo_user_delete")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function deleteAction(Request $request)
    {
        $form = $this->createFormBuilder($this->getFormDefaults())
            ->add($this->buildFormCredentials())
            ->add('apiVersion',
                'choice', [
                    'choices' => [
                        1 => 'Version 1',
                    ],
                ])
            ->add('Guid', 'text')
            ->add('Email', 'text')
            ->add('Username', 'text')
            ->add('Identifier', 'text')
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'Delete');
    }

    /**
     * @Route("/", name="_sso_demo_user_update")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function updateAction(Request $request)
    {
        $formDefaults = array_merge($this->getFormDefaults(), [ 'UpdateUserGroups' => true ]);
        $form = $this->createFormBuilder($formDefaults)
            ->add($this->buildFormCredentials())
            ->add('apiVersion', 'choice',
                [
                    'choices' =>
                        [
                            1 => 'Version 1',
                            2 => 'Version 2',
                            3 => 'Version 3',
                            4 => 'Version 4',
                            5 => 'Version 5',
                        ]
                ])
            ->add('UserKeyDataGuid', 'text')
            ->add('UserKeyDataEmail', 'text')
            ->add('UserKeyDataUsername', 'text')
            ->add('UserKeyDataIdentifier', 'text')
            ->add('Email', 'text', ['required' => false])
            ->add('Username', 'text')
            ->add('Firstname', 'text')
            ->add('Lastname', 'text')
            ->add('Password', 'text')
            ->add('Active', 'text')
            ->add('Deleted', 'text')
            ->add('AuthId', 'text')
            ->add('LdapSearchAttributes', 'text')
            ->add('LdapSearchValue', 'text')
            ->add('MfaEnabled', 'text')
            ->add('MfaRecreate', 'text')
            ->add('ActivateTokenRecreate', 'text')
            ->add('PasswordPolicy', 'text')
            ->add('LastPasswordChange', 'datetime', [
                    'required' => false
                ]
            )
            ->add('PasswordExpired', 'text')
            ->add('PasswordEncryptType', 'text')
            ->add('UpdateUserGroups', Type\CheckboxType::class)
            ->add('UserGroups', Type\CollectionType::class, [
                'block_name' => 'userGroups',
                'entry_type'    => Type\TextType::class,
                'entry_options' => [
                    'label' => false,
                ],
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'required'     => false,
                'attr' => [
                    'class' => 'dynamic-collection',
                ],
            ])
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'Update');
    }

    /**
     * @Route("/", name="_sso_demo_user_changepassword")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function changepasswordAction(Request $request)
    {
        $form = $this->createFormBuilder($this->getFormDefaults())
            ->add($this->buildFormCredentials())
            ->add('apiVersion', 'choice', ['choices' => [1 => 'Version 1', 2 => 'Version 2', 3 => 'Version 3']])
            ->add('UserKeyDataGuid', 'text')
            ->add('UserKeyDataEmail', 'text')
            ->add('UserKeyDataUsername', 'text')
            ->add('UserKeyDataIdentifier', 'text')
            ->add('Password', 'text')
            ->add('NewPassword', 'text')
            ->add('NewPasswordConfirm', 'text')
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'ChangePassword');
    }

    /**
     * @Route("/", name="_sso_demo_user_resetpassword")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function resetpasswordAction(Request $request)
    {
        $form = $this->createFormBuilder($this->getFormDefaults())
            ->add($this->buildFormCredentials())
            ->add('apiVersion', 'choice', ['choices' => [2 => 'Version 2']])
            ->add('UserKeyDataGuid', 'text')
            ->add('UserKeyDataEmail', 'text')
            ->add('UserKeyDataUsername', 'text')
            ->add('UserKeyDataIdentifier', 'text')
            ->add('Password', 'text')
            ->add('NewPassword', 'text')
            ->add('AuthToken', 'text')
            ->add('build xml and make webservice request', 'submit')
            ->getForm();

        return $this->getResponseFromForm($form, $request, 'User', 'ResetPassword');
    }

    /**
     * Add multiple dummy user
     * @param array $formData
     * @param string $controller
     * @param string $action
     * @return string
     */
    protected function stressUserAdd($formData, $controller, $action)
    {
        $users = [];
        for ($ii = 0; $ii < $formData['UserCount']; ++$ii) {
            $users[] = "<Add>" . $this->xmlRandomUser() . "</Add>";
        }
        $xml = "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($formData) . "
                        <User>" . implode('', $users) . "</User>
                    </SsoRequest>";

        return $this->callWebservice($xml, $controller, $action);
    }

    /**
     * @return string
     */
    protected function xmlRandomUser()
    {
        return "<Value>
                    <UserType>
                        <Email>" . hash('crc32', mt_rand()) . '@' . hash('crc32', mt_rand()) . ".test</Email>
                        <Username>" . hash('crc32', mt_rand()) . "</Username>
                        <Firstname>" . hash('crc32', mt_rand()) . "</Firstname>
                        <Lastname>" . hash('crc32', mt_rand()) . "</Lastname>
                        <Password>T" . hash('crc32', mt_rand()) . "_1</Password>
                        <Active>0</Active>
                    </UserType>
                </Value>";
    }

    /**
     * @param array $params
     * @return string
     */
    protected function xmlUserAdd($params)
    {
        return "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($params) . "
                        <User>
                            <Add>
                                <Value>
                                    <UserType>
                                        <Email>" . $params['Email'] . "</Email>
                                        <Username>" . $params['Username'] . "</Username>
                                        <Firstname>" . $params['Firstname'] . "</Firstname>
                                        <Lastname>" . $params['Lastname'] . "</Lastname>
                                        <Password>" . $params['Password'] . "</Password>
                                        <Active>" . $params['Active'] . "</Active>
                                        <AuthId>" . $params['AuthId'] . "</AuthId>
                                        <LdapSearchAttributes>" . $params['LdapSearchAttributes'] . "</LdapSearchAttributes>
                                        <LdapSearchValue>" . $params['LdapSearchValue'] . "</LdapSearchValue>
                                        " . (strlen($params['MfaEnabled']) ? "<MfaEnabled>" . $params['MfaEnabled'] . "</MfaEnabled>" : "") . "
                                        " . (strlen($params['PasswordPolicy']) ? "<PasswordPolicy>" . $params['PasswordPolicy'] . "</PasswordPolicy>" : "") . "
                                        " . (isset($params['LastPasswordChange']) ? "<LastPasswordChange>" . $params['LastPasswordChange']->format(\DateTime::W3C) . "</LastPasswordChange>" : "") . "
                                        " . (strlen($params['PasswordExpired']) ? "<PasswordExpired>" . $params['PasswordExpired'] . "</PasswordExpired>" : "") . "
                                        " . (strlen($params['PasswordEncryptType']) ? "<PasswordEncryptType>" . $params['PasswordEncryptType'] . "</PasswordEncryptType>" : "") . "
                                        " . $this->xmlUserGroups($params) . "
                                    </UserType>
                                </Value>
                            </Add>
                        </User>
                    </SsoRequest>";
    }

    /**
     * @var array $params
     * @return string
     */
    protected function xmlUserShow($params = array())
    {
        return "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($params) . "
                        <User>
                            <Show>
                                <Key>
                                    <UserType>" . $this->xmlBuildUserIdentifier($params) . "</UserType>
                                </Key>
                            </Show>
                        </User>
                    </SsoRequest>";
    }

    /**
     * @var array $params
     * @return string
     */
    protected function xmlUserDelete($params = array())
    {
        return "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($params) . "
                        <User>
                            <Delete>
                                <Key>
                                    <UserType>" . $this->xmlBuildUserIdentifier($params) . "</UserType>
                                </Key>
                            </Delete>
                        </User>
                    </SsoRequest>";
    }

    /**
     * @var array $params
     * @return string
     */
    protected function xmlUserUpdate($params = array())
    {
        $updateValues = array();
        foreach (array(
                     'Email',
                     'Username',
                     'Firstname',
                     'Lastname',
                     'Active',
                     'Deleted',
                     'AuthId',
                     'LdapSearchAttributes',
                     'LdapSearchValue',
                     'MfaEnabled',
                     'MfaRecreate',
                     'ActivateTokenRecreate',
                     'Password',
                     'PasswordPolicy',
                     'LastPasswordChange',
                     'PasswordExpired',
                     'PasswordEncryptType',
                 ) as $field) {
            if ('LastPasswordChange' == $field && $params[$field] instanceof \DateTime) {
                $updateValues[] = "<" . $field . ">" . $params[$field]->format(\DateTime::W3C) . "</" . $field . ">";
                continue;
            }
            if (strlen($params[$field])) {
                $updateValues[] = "<" . $field . ">" . $params[$field] . "</" . $field . ">";
            }
        }
        $updateValues[] = $this->xmlUserGroups($params);

        return "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($params) . "
                        <User>
                            <Update>
                                <Key>
                                    <UserType>" . $this->xmlBuildUserIdentifier($params, 'UserKeyData') . "</UserType>
                                </Key>
                                <Value>
                                    <UserType>" . implode("\n", $updateValues) . "</UserType>
                                </Value>
                            </Update>
                        </User>
                    </SsoRequest>";
    }

    /**
     * @var array $params
     * @return string
     */
    protected function xmlUserChangepassword($params = array())
    {
        return "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($params) . "
                        <User>
                            <ChangePassword>
                                <Key>
                                    <UserType>" . $this->xmlBuildUserIdentifier($params, 'UserKeyData') . "</UserType>
                                </Key>
                                <Value>
                                    <UserType>
                                        " . (strlen($params['Password']) ? "<Password>" . $params['Password'] . "</Password>" : "") . "
                                        " . (strlen($params['NewPassword']) ? "<NewPassword>" . $params['NewPassword'] . "</NewPassword>" : "") . "
                                        " . (strlen($params['NewPasswordConfirm']) ? "<NewPasswordConfirm>" . $params['NewPasswordConfirm'] . "</NewPasswordConfirm>" : "") . "
                                    </UserType>
                                </Value>
                            </ChangePassword>
                        </User>
                    </SsoRequest>";
    }

    /**
     * @var array $params
     * @return string
     */
    protected function xmlUserResetPassword($params = array())
    {
        return "<?xml version='1.0'?>
                    <SsoRequest>
                        " . $this->xmlCredentials($params) . "
                        <User>
                            <ResetPassword>
                                <Key>
                                    <UserType>" . $this->xmlBuildUserIdentifier($params, 'UserKeyData') . "</UserType>
                                </Key>
                                <Value>
                                    <UserType>
                                        <Password>" . $params['Password'] . "</Password>
                                        " . (strlen($params['NewPassword']) ? "<NewPassword>" . $params['NewPassword'] . "</NewPassword>" : "") . "
                                        <AuthenticationToken>" . $params['AuthToken'] . "</AuthenticationToken>
                                    </UserType>
                                </Value>
                            </ResetPassword>
                        </User>
                    </SsoRequest>";
    }

    /**
     * @param array $params
     * @return string
     */
    private function xmlUserGroups(array $params): string
    {
        if (empty($params['UpdateUserGroups'])) {
            return '';
        }

        $xmlResult = [];
        if (!empty($params['UserGroups'])) {
            foreach ($params['UserGroups'] as $userGroup) {
                if (0 < strlen($userGroup)) {
                    $xmlResult[] = '<UserGroup>' . $userGroup . '</UserGroup>';
                }
            }
        }

        return '<UserGroups>' . implode(PHP_EOL, $xmlResult) . '</UserGroups>';
    }
}
