<?php
namespace Backend\BaseBundle\EventListener;

use Backend\BaseBundle\Service\OperationLogger;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\Tag;
use JMS\DiExtraBundle\Annotation\Inject;
use JMS\DiExtraBundle\Annotation\InjectParams;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Backend\BaseBundle\Model;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;

/**
 * @Service
 * @Tag("kernel.event_listener", attributes = {"public": false, "event": "kernel.request", "method": "onKernelRequestLoginCheck", "priority": 10})
 * @Tag("kernel.event_listener", attributes = {"public": false, "event": "kernel.request", "method": "onKernelRequestSlugCheck"})
 * @Tag("kernel.event_listener", attributes = {"public": false, "event": SecurityEvents::INTERACTIVE_LOGIN, "method": "onInteractiveLoginEvent"})
 */
class LoginCheckRequestListener
{

    /** @var  \Backend\BaseBundle\Security\SiteUserProvider */
    protected $userProvider;

    /** @var  \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface */
    protected $tokenStorage;

    /** @var  Session */
    protected $session;

    /** @var  OperationLogger */
    protected $logger;

    /**
     * @InjectParams({
     *    "userProvider" = @Inject("site_user_provider")
     * })
     */
    public function injectSiteUserProvider($userProvider)
    {
        $this->userProvider = $userProvider;
    }

    /**
     * @InjectParams({
     *    "tokenStorage" = @Inject("security.token_storage")
     * })
     */
    public function injectTokenStorage($tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    /**
     * @InjectParams
     */
    public function injectSession(Session $session)
    {
        $this->session = $session;
    }

    /**
     * @InjectParams({
     *     "logger" = @Inject("backend.base_bundle.operationlog")
     * })
     */
    public function injectOperationLogger(OperationLogger $logger)
    {
        $this->logger = $logger;
    }

    public function onKernelRequestLoginCheck(GetResponseEvent $event)
    {
        if(!$event->isMasterRequest()) {
            return;
        }

        $request = $event->getRequest();
        if($request->attributes->get('_route') != '@BackendLoginCheck'){
            return;
        }

        $this->userProvider->setSlug($request->attributes->get('slug'));
    }

    public function onKernelRequestSlugCheck(GetResponseEvent $event)
    {
        if(!$event->isMasterRequest()) {
            return;
        }

        if(null === ($slug = $event->getRequest()->attributes->get('slug'))){
            return ;
        }

        if(!($token = $this->tokenStorage->getToken())){
            return;
        }

        if(!($user = $token->getUser())){
            return;
        }

        if(!($user instanceof Model\SiteUser)){
            return;
        }

        if($user->getSiteSlug() != $slug || !$user->getSite()->canLoginBackend()){
            throw new AccessDeniedException();
        }

        $this->session->set('Site', $user->getSite());
    }

    public function onInteractiveLoginEvent(InteractiveLoginEvent $event)
    {
        /** @var Model\SiteUser $user */
        $user = $event->getAuthenticationToken()->getUser();
        if(!($user instanceof Model\SiteUser)){
            return;
        }
        $user->setLastLogin(time());
        $user->save();
        //$this->saveOperationlog($user);
        $this->logger->log($user, 'login', 'loginname '.$user->getLoginName());
    }

    /**
     * @param $user
     * @throws \Exception
     * @throws \PropelException
     */
    protected function saveOperationlog(Model\SiteUser $user)
    {
        $this->logger->log($user, 'login', $user->getLoginName());
    }
}