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

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sso\BackendSecurityBundle\Form\User as UserForm;
use Sso\BackendSecurityBundle\Entity\User as UserEntity;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Class UserController
 * @package Sso\BackendSecurityBundle\Controller
 */
class UserController extends Controller
{

    /**
     * FOS user manager
     * @var \FOS\UserBundle\Doctrine\UserManager
     */
    private $userManager;

    /**
     * List backend users
     * @Route("/", name="_sso_backend_security_user")
     * @Template()
     */
    public function indexAction()
    {
        return array(
            'entities' => $this->userManager()->findUsers(),
        );
    }

    /**
     * Edit backend user
     * @Route("/", name="_sso_backend_security_user_edit")
     * @Template()
     * @param int $userId
     * @return Response
     * @throws NotFoundHttpException
     */
    public function editAction($userId)
    {
        $entity = $this->userManager()->findUserBy(array('id' => $userId));
        if (!$entity) {
            throw $this->createNotFoundException('User not found!');
        }

        $editForm = $this->createEditForm($entity);
        $deleteForm = $this->createDeleteForm($userId);

        return [
            'entity' => $entity,
            'edit_form' => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ];
    }

    /**
     * New backend user
     * @return Response
     */
    public function newAction()
    {
        $entity = $this->userManager()->createUser();
        $form = $this->createCreateForm($entity);

        return $this->render('SsoBackendSecurityBundle:User:new.html.twig', array(
            'entity' => $entity,
            'form' => $form->createView(),
        ));
    }

    /**
     * Create new backend user
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @return Response
     */
    public function createAction(Request $request)
    {
        $entity = $this->userManager()->createUser();
        $form = $this->createCreateForm($entity);
        $form->handleRequest($request);

        if ($form->isValid()) {

            // Generate random password, if empty
            if ($form->has('PlainPassword') && $form->get('PlainPassword')->isEmpty()) {
                $entity->setPlainPassword(hash('sha256', mt_rand() . '#' . microtime()));
            }

            $this->userManager()->updateUser($entity);
            $this->get('session')->getFlashBag()->add('success', 'User created success');

            return $this->redirect($this->generateUrl('_sso_backend_security_user_show',
                array('userId' => $entity->getId())));
        }

        return $this->render('SsoBackendSecurityBundle:User:new.html.twig', array(
            'entity' => $entity,
            'form' => $form->createView(),
        ));
    }

    /**
     * Update backend user
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @param int $userId
     * @return string
     */
    public function updateAction(Request $request, $userId)
    {
        $entity = $this->userManager()->findUserBy(array('id' => $userId));
        if (!$entity) {
            throw $this->createNotFoundException('User not found!');
        }
        $deleteForm = $this->createDeleteForm($userId);
        $editForm = $this->createEditForm($entity);
        $editForm->handleRequest($request);

        if ($editForm->isValid()) {
            $this->userManager()->updateUser($entity);
            $this->get('session')->getFlashBag()->add('info', 'User Saved Success');

            return $this->redirect(
                $this->generateUrl('_sso_backend_security_user_edit',
                    array('userId' => $userId))
            );
        }

        return $this->render(
            'SsoBackendSecurityBundle:User:edit.html.twig',
            array(
                'entity' => $entity,
                'edit_form' => $editForm->createView(),
                'delete_form' => $deleteForm->createView(),
            )
        );
    }

    /**
     * Creates a form to edit a user entity.
     * @param \Sso\BackendSecurityBundle\Entity\User $entity The entity
     *
     * @return \Symfony\Component\Form\Form The form
     */
    private function createEditForm(UserEntity $entity)
    {
        $form = $this->createForm(new UserForm($this->getUserRoleHierarchy()), $entity, array(
            'action' => $this->generateUrl(
                '_sso_backend_security_user_update',
                array('userId' => $entity->getId())
            ),
            'method' => 'PUT',
        ));
        if ($form->has('Password')) {
            $form->get('Password')->setData('');
        }

        $form->add('submit', 'submit', array('label' => 'Update'));

        return $form;
    }

    /**
     * Creates a form to create a user entity.
     * @param \Sso\BackendSecurityBundle\Entity\User $entity The entity
     * @return \Symfony\Component\Form\Form The form
     */
    private function createCreateForm(UserEntity $entity)
    {
        $form = $this->createForm(new UserForm($this->getUserRoleHierarchy()), $entity, array(
            'action' => $this->generateUrl('_sso_backend_security_user_create'),
            'method' => 'POST',
        ));

        $form->add('submit', 'submit', array('label' => 'Create'));

        return $form;
    }

    /**
     * Creates a form to delete a user entity by id.
     * @param mixed $userId The entity id
     * @return \Symfony\Component\Form\Form
     */
    private function createDeleteForm($userId)
    {
        return $this->createFormBuilder()
            ->setAction($this->generateUrl('_sso_backend_security_user_delete', array('userId' => $userId)))
            ->setMethod('DELETE')
            ->add('submit', 'submit', array('label' => 'Delete'))
            ->getForm();
    }

    /**
     * Delete backend user
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @param int $userId
     * @return RedirectResponse
     */
    public function deleteAction(Request $request, $userId)
    {
        $form = $this->createDeleteForm($userId);
        $form->handleRequest($request);

        $entity = $this->userManager()->findUserBy(array('id' => $userId));
        if (!$entity) {
            throw $this->createNotFoundException('Unable to find User entity.');
        }

        $this->userManager()->deleteUser($entity);
        $this->get('session')->getFlashBag()->add('success', 'User deleted.');

        return $this->redirect($this->generateUrl('_sso_backend_security_user'));
    }

    /**
     * Show backend user
     * @param int $userId
     * @return Response
     * @throws NotFoundHttpException
     */
    public function showAction($userId)
    {
        $entity = $this->userManager()->findUserBy(array('id' => $userId));
        if (!$entity) {
            throw $this->createNotFoundException('Unable to find user entity.');
        }

        $deleteForm = $this->createDeleteForm($userId);

        return $this->render('SsoBackendSecurityBundle:User:show.html.twig', [
            'entity' => $entity,
            'delete_form' => $deleteForm->createView(),
        ]);
    }

    /**
     * Get admin users role hierarchy
     * @return array
     */
    private function getUserRoleHierarchy()
    {
        $roles = $this->container->getParameter('security.role_hierarchy.roles');

        return $roles ? $roles : [];
    }

    /**
     * Get FOS user manager
     * @return \FOS\UserBundle\Doctrine\UserManager
     */
    private function userManager()
    {
        return null !== $this->userManager ? $this->userManager : $this->get('fos_user.user_manager');
    }
}
