<?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 LifeStyle\SamlAuthBundle\Security\User;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use LifeStyle\SamlAuthBundle\Model\UserData\User as UserDto;
use LifeStyle\SamlAuthBundle\Configuration\SamlConfig;

/**
 * Class SamlUserProvider
 * @package LifeStyle\SamlAuthBundle\Security\User
 */
class SamlUserProvider implements UserProviderInterface
{
    /**
     * @var SamlConfig;
     */
    private $config;

    /**
     * SamlUserProvider constructor.
     */
    public function __construct(SamlConfig $config)
    {
        $this->config = $config;
    }

    /**
     * @param string $username
     * @return UserInterface|void
     */
    public function loadUserByUsername($username)
    {
        unset($username);
        // this provider can't be used with loadUserByUsername() as it pulls it's actual userinfo from the DTO
        // holding all user details we got from the IdP/SAML request.
        // So, lets just always throw the exception to ensure proper compatibility with the rest of the framework.
        throw new UsernameNotFoundException();
    }


    /**
     * Loads the user for the given username from the user DTO holding IdP/SAML details.
     * @param UserDto $user The user DTO
     * @return UserInterface
     * @throws UsernameNotFoundException if the user data is invalid
     */
    public function loadUserFromDto(UserDto $user)
    {
        $roles[] = 'ROLE_USER';

        if (count($user->getUserApplications()) > 0) {
            foreach ($user->getUserApplications() as $name => $application) {
                if ($this->config->getIdpAppName() === $name) {

                    foreach ($application->getRoles() as $role) {
                        $roles[] = $role->getName();
                    }
                }
                break;
            }

        }
        return new SamlUser($user, $roles);
    }

    /**
     * Refreshes the user for the account interface.
     *
     * It is up to the implementation to decide if the user data should be
     * totally reloaded (e.g. from the database), or if the UserInterface
     * object can just be merged into some internal array of users / identity
     * map.
     *
     * @param UserInterface $user
     * @throws UnsupportedUserException if the account is not supported
     */
    public function refreshUser(UserInterface $user)
    {
        unset($user);
        //not allowed
        throw new UnsupportedUserException();
    }

    /**
     * Whether this provider supports the given user class.
     * @param string $class
     * @return bool
     */
    public function supportsClass($class)
    {
        return $class === static::class;
    }
}
