<?php

/**
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is protected 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
 * @version    $Id:$
 * @link       http://www.life-style.de
 */

namespace LifeStyle\Tools\CredentialsBundle\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use LifeStyle\Tools\WebserviceBundle\Event\FilterCredentialsEvent;
use LifeStyle\Tools\WebserviceBundle\Event\Credentials as CredentialsEvents;
use LifeStyle\Tools\WebserviceBundle\Exception\InvalidCredentialsException;
use LifeStyle\Tools\CredentialsBundle\Api\Manager as ApiManager;
use LifeStyle\Tools\WebserviceBundle\Error\Type\External as ExternalError;
use LifeStyle\Tools\WebserviceBundle\Validator\Xml as XmlValidator;
use Symfony\Component\HttpFoundation\RequestStack;
use Sso\Tools\UserIdentifierBundle\Api\Controller as IdpController;

/**
 * Class ValidateUserIdentifierListener
 * @package LifeStyle\Tools\CredentialsBundle\EventListener
 */
class ValidateUserIdentifierListener implements EventSubscriberInterface
{
    /**
     * Api manager
     *
     * @var ApiManager
     */
    protected $apiM;

    /**
     *
     * @var RequestStack
     */
    protected $requestStack;

    /**
     * @var IdpController
     */
    private $idpController;

    /**
     * ValidateUserIdentifierListener constructor.
     * @param ApiManager $apiM
     * @param IdpController $idpController
     * @param RequestStack $requestStack
     */
    public function __construct(ApiManager $apiM, IdpController $idpController, RequestStack $requestStack)
    {
        $this->apiM = $apiM;
        $this->idpController = $idpController;
        $this->requestStack = $requestStack;
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return array(CredentialsEvents::VALIDATE_SERVICETRIGGER => 'onValidateServiceTrigger');
    }

    /**
     * @param FilterCredentialsEvent $event
     */
    public function onValidateServiceTrigger(FilterCredentialsEvent $event)
    {
        if (null === ($xml = $event->getServiceTrigger())) {
            $this->exception('cr14', 'UserIdentifierInvalidIdentifier');
        }
        if (!$this->validateXml($xml)) {
            $this->exception('cr15', 'UserIdentifierInvalidIdentifier');
        }

        $username = (string)$xml->Username;
        $userIdentifier = (string)$xml->UserIdentifier;

        if (empty($username)) {
            $this->exception('cr16', 'UserIdentifierInvalidIdentifier');
        }

        if (empty($username)) {
            $this->exception('cr17', 'UserIdentifierInvalidIdentifier');
        }

        $validCredentials = $this->idpController->userIdentifierValidate($username, $userIdentifier);

        if (!$validCredentials) {
            $this->exception('cr18', 'UserIdentifierInvalidIdentifier');
        }
    }

    /**
     * Validate xml for mandatory nodes
     *
     * @param \DOMElement $xml
     */
    private function validateXml($xml)
    {
        $validator = new XmlValidator();
        if ($validator->validate($xml, $validator->strToXml($this->xmlAllowedElements()))) {
            return true;
        }
        $this->apiM->errors()->addErrors($validator->errors()->getErrors());
        return false;
    }

    /**
     * Xml structure for credentials
     *
     * @return string
     */
    private function xmlAllowedElements()
    {
        return '<Username required="true" />'
            . '<UserIdentifier required="true" />';
    }

    /**
     * Add error and throw exception
     *
     * @param string $errorCode
     * @param string $shortMessage
     * @throws InvalidCredentialsException
     */
    private function exception($errorCode, $shortMessage)
    {
        $this->apiM->errors()->addError(new ExternalError($errorCode, $shortMessage));
        throw new InvalidCredentialsException();
    }


}
