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

use AppBundle\Api\Manager as ApiManager;
use LifeStyle\Tools\SamlBundle\Saml\SamlControllerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Sso\WebserviceBundle\Configuration\WsRoute;
use Sso\WebserviceBundle\Configuration\WsSecurity;
use Sso\WebserviceBundle\Error\Type\External as ExternalError;

/**
 * Class UserIdentifierController
 *
 * @copyright  2017 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package AppBundle\Controller
 */
class UserIdentifierController extends AbstractController
{
    /**
     * @var ApiManager
     */
    private $apiManager;

    /**
     * SAML Controller
     *
     * @var SamlControllerInterface
     */
    private $samlController;

    /**
     * UserIdentifierController constructor.
     * @param ApiManager $apiManager
     * @param SamlControllerInterface $samlController
     */
    public function __construct(ApiManager $apiManager, SamlControllerInterface $samlController)
    {
        $this->apiManager = $apiManager;
        $this->samlController = $samlController;
    }

    /**
     * Get user-identifier
     *
     * @Route("/", methods={"POST"}, condition="request.headers.get('API-CONTROLLER') == 'UserIdentifier' and request.headers.get('API-ACTION') == 'Get'")
     * @WsRoute()
     * @WsSecurity({"ServiceProvider", "ServiceCountry"})
     */
    public function getAction(Request $request)
    {
        $xmlRequest = $request->attributes->get('XmlRequest');
        $requestModel = $this->apiManager->modelFactory()->request()->userIdentifier()->get($xmlRequest->UserIdentifier->Get);
        $userModel = $requestModel->getUserModel();

        // Use random cookie to force credentials check on each request @see BLIT-180
        if (!$this->apiManager->errors()->hasErrors()) {
            $this->apiManager->cookieCache()->setFilename(md5(uniqid() . mt_rand()));
            if (!$this->samlController->login($userModel->getUsername(), $userModel->getPassword())) {

                // Force logout, if password check has failed
                $this->apiManager->cookieCache()->setFilename(md5($userModel->getUsername() . ':' . $userModel->getPassword()));
                $this->samlController->logout($userModel->getUsername());

                $this->apiManager->errors()->addError(new ExternalError('ui011', 'UserIdentifierInvalidCredentials'));
            }
        }

        // Check credentials again with current cookie, to receive userIdentifier from earlier request
        if (!$this->apiManager->errors()->hasErrors()) {
            $this->apiManager->cookieCache()->setFilename(md5($userModel->getUsername() . ':' . $userModel->getPassword()));
            if (!$this->samlController->login($userModel->getUsername(), $userModel->getPassword())) {
                $this->apiManager->errors()->addError(new ExternalError('ui012', 'UserIdentifierInvalidCredentials'));
            }
        }

        // For validation we need a cookie, which can be identified by username and userIdentifier
        if (!$this->apiManager->errors()->hasErrors()) {
            $userModel
                    ->setUserIdentifier($this->samlController->getAttribute('useridentifier'))
                    ->setSessionLifetime($this->samlController->getSessionLifetime());
            $requestModel->setUserModel($userModel);

            $this->apiManager->cookieCache()->copyCookie(md5($userModel->getUsername() . ':' . $userModel->getUserIdentifier()));
        }
        $this->apiManager->modelFactory()->response()->userIdentifier()->get($requestModel);

        return new Response($this->apiManager->responseBuilder()->output(), 200, array('Content-Type' => 'text/xml; charset=UTF-8'));
    }

    /**
     * Validate user-identifier
     *
     * @Route("/", methods={"POST"}, condition="request.headers.get('API-CONTROLLER') == 'UserIdentifier' and request.headers.get('API-ACTION') == 'Validate'")
     * @WsRoute()
     * @WsSecurity({"ServiceProvider", "ServiceCountry", "ServiceTrigger"})
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function validateAction(Request $request)
    {
        $xmlRequest = $request->attributes->get('XmlRequest');
        $requestModel = $this->apiManager->modelFactory()->request()->userIdentifier()->validate($xmlRequest->UserIdentifier->Validate);
        $userModel = $requestModel->getUserModel();

        $session = null;
        if (!$this->apiManager->errors()->hasErrors()) {

            $session = $this->apiManager->userIdentifierHandler()->validate($userModel->getUserIdentifier(), $userModel->getUsername());
            if (null === $session) {
                $this->apiManager->errors()->addError(new ExternalError('ui021', 'UserIdentifierInvalidIdentifier'));
            }
        }
        if (null !== $session) {
            $userModel
                    ->setUserIdentifier($session->getUserIdentifier())
                    ->setSessionLifetime($session->getExpire()->format('U'));
            $requestModel->setUserModel($userModel);
        }
        $this->apiManager->modelFactory()->response()->userIdentifier()->validate($requestModel);

        return new Response($this->apiManager->responseBuilder()->output(), 200, array('Content-Type' => 'text/xml; charset=UTF-8'));
    }
}
