<?php 

namespace NPS\DependencyInjection;

use NPS\Model\User;
use NPS\Model\KnowledgeBase;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

/**
 * Restricts access of a user to specific knowledge bases
 * @author Lukas Korinek
 */
final class UserKnowledgeAccessGuard
{

    /** @var AuthorizationCheckerInterface $auth */
    private $auth;

    /** @var bool $grantOverride Knowledge access override, makes grants inapplicable */
    private $grantOverride;

    public function __construct(AuthorizationCheckerInterface $auth, $grantOverride)
    {
        $this->auth = $auth;
        $this->grantOverride = $grantOverride;
    }

    /**
     * Determines if a user has access to the knowledge base
     * @param KnowledgeBase $base
     * @param User|null $user
     * @return bool
     */
    public function hasAccess(KnowledgeBase $base, User $user = null)
    {
        if(!$this->filterByStatus($base, $user))
        {
            return false;
        }

        if($user && !$this->grantOverride)
        {
            return $this->filterByGrants($base, $user);
        }

        return true;
    }

    /**
     * Filters list of knowledge bases for a user
     * @param array $knowledgeBases
     * @param User $user 
     * @return array
     */
    public function filterAccessible(array $knowledgeBases, User $user = null)
    {
        return array_filter($knowledgeBases, function($base) use ($user)
        {
            return $this->hasAccess($base, $user);
        });        
    }

    ////////////////////////////////////////////////////////////////

    /**
     * Filters access by knowledge base status
     * @param KnowledgeBase $base
     * @param User $user
     * @return false 
     */
    private function filterByStatus(KnowledgeBase $base, User $user = null)
    {
        if($base->getStatus() == KnowledgeBase::STATUS_DISABLED)
        {
            return false;
        }

        if(!$user)
        {
            return $base->getStatus() == KnowledgeBase::STATUS_DEMO;
        }

        if($this->auth->isGranted('ROLE_ADMIN'))
        {
            return true;
        }

        if(!$this->auth->isGranted('ROLE_ENGINEER'))
        {
            if(!$this->auth->isGranted('ROLE_TESTER'))
            {
                return $base->getStatus() == KnowledgeBase::STATUS_PUBLIC || $base->getStatus() == KnowledgeBase::STATUS_DEMO;
            }

            return $base->getStatus() != KnowledgeBase::STATUS_DEV;
        }

        return true;
    }

    /**
     * Filters by applicable user grants
     * @param KnowledgeBase $base
     * @param User $user
     * @return bool
     */
    private function filterByGrants(KnowledgeBase $base, User $user)
    {
        return in_array($base->getKnowledgeBaseBindId(), $user->getGrants());
    }
}

