<?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\Api\Controller;

use Sso\WebserviceBundle\Api\Error\Type\External as ExternalError;
use Sso\WebserviceBundle\Api\Response\Builder as XmlResponse;

/**
 * Class UserApplicationRoleController
 * @package Sso\WebserviceBundle\Api\Controller
 */
class UserApplicationRoleController extends AbstractController
{

    /**
     * Returns list of available actions
     * @return array
     */
    protected function _getActions()
    {
        return array(
            'Add',
            'Delete',
            'Show',
        );
    }

    /**
     * Show users application role list
     * @param \SimpleXMLElement $xmlRequest
     * @param XmlResponse $xmlResponse
     */
    protected function show(\SimpleXMLElement $xmlRequest, XmlResponse $xmlResponse)
    {
        $requestModel = $this->modelFactory->request()->userApplicationRole()->show($xmlRequest);
        $userModel = $requestModel->getUserModel();
        $applicationModel = $requestModel->getApplicationModel();

        if (!$requestModel->hasErrors() && !($user = $this->dbM->user()->getUserByUser($userModel))) {
            $requestModel->addError(new ExternalError('uar011', 'UserNotFound'));
        }
        if (!$requestModel->hasErrors() && !$this->apiM->userAuthorization()->canUpdate($user)) {
            $requestModel->addError(new ExternalError('uar013', 'UserNotAuthorized'));
        }
        if (!$requestModel->hasErrors() && !($application = $this->dbM->application()->getApplicationByName($applicationModel->getName()))) {
            $requestModel->addError(new ExternalError('uar012', 'ApplicationNotFound'));
        }
        //check read on application
        if (!$requestModel->hasErrors() && !in_array($applicationModel->getName(),
                $this->apiM->userRolesApplicationRead())
        ) {
            $requestModel->addError(new ExternalError('ac001', 'ApplicationAccessDenied',
                'You are not allowed to read this Application'));
        }
        if (!$requestModel->hasErrors() && !($userApplication = $this->dbM->userApplication()->getUserApplication($user,
                $application))
        ) {
            $requestModel->addError(new ExternalError('uar013', 'UserApplicationNotFound'));
        }
        if (!$requestModel->hasErrors()) {
            $requestModel->setUserModel($user);
            $requestModel->setApplicationModel($application);
            $requestModel->setUserApplicationModel($userApplication);
        }
        $this->modelFactory->response($xmlResponse)->userApplicationRole()->show($requestModel);
    }

    /**
     * Add application role to user
     *
     * @param \SimpleXMLElement $xmlRequest
     * @param XmlResponse $xmlResponse
     */
    protected function add(\SimpleXMLElement $xmlRequest, XmlResponse $xmlResponse)
    {
        $requestModel = $this->modelFactory->request()->userApplicationRole()->add($xmlRequest);
        $userModel = $requestModel->getUserModel();
        $applicationModel = $requestModel->getApplicationModel();
        $userApplicationRoles = $requestModel->getUserApplicationRoles();

        if (!$requestModel->hasErrors() && !($user = $this->dbM->user()->getUserByUser($userModel))) {
            $requestModel->addError(new ExternalError('uar021', 'UserNotFound'));
        }
        if (!$requestModel->hasErrors() && !$this->apiM->userAuthorization()->canUpdate($user)) {
            $requestModel->addError(new ExternalError('uar013', 'UserNotAuthorized'));
        }
        if (!$requestModel->hasErrors() && !($application = $this->dbM->application()->getApplicationByName($applicationModel->getName()))) {
            $requestModel->addError(new ExternalError('uar022', 'ApplicationNotFound'));
        }
        //check write on application
        if (!$requestModel->hasErrors() && !in_array($applicationModel->getName(),
                $this->apiM->userRolesApplicationWrite())
        ) {
            $requestModel->addError(new ExternalError('ac001', 'ApplicationAccessDenied',
                'You are not allowed to write this Application'));
        }
        if (!$requestModel->hasErrors() && !($userApplication = $this->dbM->userApplication()->getUserApplication($user,
                $application))
        ) {
            $requestModel->addError(new ExternalError('uar023', 'UserApplicationNotFound'));
        }

        // Collect roles to add
        $addUserApplicationRoles = array();
        if (!$requestModel->hasErrors()) {
            foreach ($userApplicationRoles as $userApplicationRole) {
                if (!($role = $application->getRole($userApplicationRole->getName()))) {
                    $userApplicationRole->errors()->addError(new ExternalError('uar024', 'ApplicationRoleNotFound',
                        'Role "'.$userApplicationRole->getName().'" not found. Application "'.$application->getName().'" does not have this role'));
                    continue;
                }
                if (!$userApplication->hasRole($userApplicationRole)) {

                    $userApplicationRole->setUserApplication($userApplication);
                    $userApplicationRole->setRole($role);
                    if (null !== $userApplicationRole->getActive()) {
                        $userApplicationRole->setActive($userApplicationRole->getActive() == 1 ? 1 : 0);
                    } else {
                        $userApplicationRole->setActive(1);
                    }
                    $addUserApplicationRoles[] = $userApplicationRole;
                } else {
                    //maybe we have to update the role active status
                    $role = $userApplication->getRole($userApplicationRole->getName());
                    if (null !== $userApplicationRole->getActive()) {
                        $role->setActive($userApplicationRole->getActive() == 1 ? 1 : 0);
                    }
                }
            }
        }

        // Save roles
        if (!$requestModel->hasErrors()) {
            $this->dbM->userApplicationRole()->addUserApplicationRoles($addUserApplicationRoles);
        }

        if (!$requestModel->hasErrors()) {
            $userApplication->checkObjectUpdate();
            $this->dbM->userApplication()->saveUserApplication($userApplication);
        }

        $this->modelFactory->response($xmlResponse)->userApplicationRole()->add($requestModel);
    }

    /**
     * Delete application role from user
     *
     * @param \SimpleXMLElement $xmlRequest
     * @param XmlResponse $xmlResponse
     */
    protected function delete(\SimpleXMLElement $xmlRequest, XmlResponse $xmlResponse)
    {
        $requestModel = $this->modelFactory->request()->userApplicationRole()->delete($xmlRequest);
        $userModel = $requestModel->getUserModel();
        $applicationModel = $requestModel->getApplicationModel();
        $userApplicationRoles = array($requestModel->getRoleModel());

        if (!$requestModel->hasErrors() && !($user = $this->dbM->user()->getUserByUser($userModel))) {
            $requestModel->addError(new ExternalError('uar041', 'UserNotFound'));
        }
        if (!$requestModel->hasErrors() && !$this->apiM->userAuthorization()->canUpdate($user)) {
            $requestModel->addError(new ExternalError('uar013', 'UserNotAuthorized'));
        }
        if (!$requestModel->hasErrors() && !($application = $this->dbM->application()->getApplicationByName($applicationModel->getName()))) {
            $requestModel->addError(new ExternalError('uar042', 'ApplicationNotFound'));
        }
        //check write on application
        if (!$requestModel->hasErrors() && !in_array($applicationModel->getName(),
                $this->apiM->userRolesApplicationWrite())
        ) {
            $requestModel->addError(new ExternalError('ac001', 'ApplicationAccessDenied',
                'You are not allowed to write this Application'));
        }
        if (!$requestModel->hasErrors() && !($userApplication = $this->dbM->userApplication()->getUserApplication($user,
                $application))
        ) {
            $requestModel->addError(new ExternalError('uar043', 'UserApplicationNotFound'));
        }

        // Collect roles to delete
        $deleteUserApplicationRoles = array();
        if (!$requestModel->hasErrors()) {
            foreach ($userApplicationRoles as $userApplicationRole) {
                if (($role = $userApplication->getRole($userApplicationRole->getName()))) {
                    $deleteUserApplicationRoles[] = $role;
                } else {
                    $requestModel->addError(new ExternalError('uar044', 'UserApplicationRoleNotFound'));
                }
            }
        }

        // Delete roles for users application
        if (!$requestModel->hasErrors() && !$this->dbM->userApplicationRole()->deleteUserApplicationRoles($deleteUserApplicationRoles)) {
            foreach ($deleteUserApplicationRoles as $role) {
                $requestModel->addErrors($role->errors()->getErrors());
            }
        }

        $this->modelFactory->response($xmlResponse)->userApplicationRole()->delete($requestModel);
    }
}
