<?php

namespace AppBundle\Controller;

use AppBundle\Entity\Company;
use AppBundle\Enum\UserType;
use AppBundle\Form\Type\Front\User\ProfileIngeFormType;
use AppBundle\Form\Type\Front\User\ProfileProfFormType;
use AppBundle\Mail\ItdlcMailer;
use AppBundle\Mail\NewsletterMailer;
use FOS\UserBundle\Controller\ProfileController as BaseController;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Liip\ImagineBundle\Controller\ImagineController;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
 * 
 */
class ProfileController extends BaseController
{
    /**
     * @var CacheManager
     */
    private $cacheManager;

    /**
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    /**
     * @var ItdlcMailer
     */
    private $itdlcMailer;

    /**
     * @var ImagineController
     */
    private $imagineController;

    /**
     * @var NewsletterMailer
     */
    private $newsletterMailer;

    /**
     * @var UserManagerInterface
     */
    private $userManager;

    /**
     * @var TranslatorInterface
     */
    private $translator;
    
    public function __construct(
        CacheManager $cacheManager, 
        EventDispatcherInterface $dispatcher,
        ImagineController $imagineController,
        ItdlcMailer $itdlcMailer,
        NewsletterMailer $newsletterMailer,
        UserManagerInterface $userManager,
        TranslatorInterface $translator
    )
    {
        $this->cacheManager = $cacheManager;
        $this->dispatcher = $dispatcher;
        $this->imagineController = $imagineController;
        $this->itdlcMailer = $itdlcMailer;
        $this->newsletterMailer = $newsletterMailer;
        $this->userManager = $userManager;
        $this->translator = $translator;
    }

    /**
     * Edit the user
     * @param Request $request
     * @return null|RedirectResponse|Response
     */
    public function editAction(Request $request)
    {
        $user = $this->getUser();
        if (!is_object($user) || !$user instanceof UserInterface) {
            throw $this->createAccessDeniedException('This user does not have access to this section.');
        }

        $old_data = clone $user;

        $event = new GetResponseUserEvent($user, $request);
        $this->dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_INITIALIZE, $event);

        if (null !== $event->getResponse()) {
            return $event->getResponse();
        }
        
        $formTypeClass = UserType::TEACHER === $user->getType()
            ? ProfileProfFormType::class
            : ProfileIngeFormType::class
        ;
        $form = $this->createForm($formTypeClass, $user);
        $form->handleRequest($request);
        
        if ($form->isSubmitted() && $form->isValid()) {
            $isValid = true;
            
            if (
                $old_data->getEmail() !== $user->getEmail()
                || $form->get('plainPassword')->getData() != null
            ) {
                // Check Password
                $constraints = array(
                    new NotBlank(),
                    new UserPassword(array('message' => $this->translator->trans('form.profile.password.current_password.invalid', array(), 'form'))),
                );
                $errors = $this->get('validator')->validate(
                    $form->get('current_password')->getData(),
                    $constraints 
                );

                if ($errors->count() > 0) {
                    foreach ($errors as $e) {
                        $formError = new FormError($e->getMessage());
                        $form->get('current_password')->addError($formError);
                    }
                    $isValid = false;
                }
                
            }

            if  ($isValid) {
                // If the enginner set a custom company, first check if it does not already exists.
                // If not, then create it.
                if (UserType::ENGINEER === $user->getType() && $companyName = $form->get('establishmentNameOther')->getData()) {
                    
                    $em = $this->getDoctrine()->getManager();
                    $company = $em->getRepository(Company::class)->findOneByName($companyName);

                    if (!$company) {
                        $company = new Company();
                        $company->setName($companyName);
                        $company->setAvailableForUsers(true);

                        $em->persist($company);
                        $em->flush();
                    }

                    $user->setEstablishment($company);
                }

                // Remove profile picture if necessary
                $photoPath = $user->getWebPhoto();
                if (null !== $request->get('remove_picture') && $user->removePhoto()) { // Remove the original
                    $this->cacheManager->remove($photoPath); // Remove all the thumbnails
                }

                $event = new FormEvent($form, $request);
                $this->dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_SUCCESS, $event);

                $this->userManager->updateUser($user);

                // Generate the thumbnail version of the uploaded profile picture if necessary
                if (null !== $user->getWebPhoto()) {
                    // Generate the thumbnail of the new picture
                    $this->imagineController->filterAction($request, $user->getWebPhoto(), '48Lx48H');
                }

                if (null === $response = $event->getResponse()) {
                    // $this->addFlash('info', 'Profil modifié'); // We have already a flash : See FlashListener in friendsofsymfony bundle

                    // Newsletter
                    $this->newsletterMailer->subscribe($user);

                    $url = $this->generateUrl('fos_user_profile_edit');
                    $response = new RedirectResponse($url);
                }

                $this->dispatcher->dispatch(
                    FOSUserEvents::PROFILE_EDIT_COMPLETED,
                    new FilterUserResponseEvent($user, $request, $response)
                );

                return $response;
            }
        } else if ($form->isSubmitted()) { // Form submitted but not valid
            $this->addFlash('error', $this->translator->trans('notice.profile.not_valid', array(), 'notice'));
        }

        return $this->render('FOSUserBundle:Profile:edit.html.twig', array(
            'form' => $form->createView(),
            'is_available' => $user->getIsAvailable()
        ));
    }

    /**
     * Supprime la carte d'identité référencée par l'utilisateur, selon la valeur du paramètre card_number passé en POST.
     * card_number doit être un entier indiquant la méthode de l'entité User à appeler ()
     *
     * @Route(
     *      "/espace-perso/delete-identity",
     *      name = "espace_perso_delete_identity"
     * )
     * @Method("POST")
     *
     * @param Request $request
     * @return Response
     */
    public function deleteIdentityAction(Request $request)
    {
        $response = new Response();
        $user = $this->getUser();
        if (!is_object($user) || !$user instanceof UserInterface) {
            throw $this->createAccessDeniedException('This user does not have access to this section.');
        }

        if ('POST' === $request->getMethod()) {
            $card_number = $request->get('card_number');

            switch ($card_number) {
                case 1:
                    $user->setIdentityCard1(null);
                    $this->userManager->updateUser($user);
                    break;

                case 2:
                    $user->setIdentityCard2(null);
                    $this->userManager->updateUser($user);
                    break;

                default:
                    $response->setStatusCode(Response::HTTP_NOT_FOUND);
                    break;
            }
        } else {
            $response->setStatusCode(Response::HTTP_METHOD_NOT_ALLOWED);
        }

        return $response;
    }

    /**
     * Change la valeur Disponible du profil
     *
     * @Route(
     *      "/espace-perso/toggle-availability",
     *      name = "espace_perso_toggle_availability"
     * )
     * @Method("POST")
     *
     * @param Request $request
     * @return Response
     */
    public function toggleAvailabilityAction(Request $request)
    {
        $response = new Response();
        $user = $this->getUser();
        if (!is_object($user) || !$user instanceof UserInterface) {
            throw $this->createAccessDeniedException('This user does not have access to this section.');
        }

        if ('POST' === $request->getMethod()) {
            $is_available = (bool) $request->get('is_available');

            $user->setIsAvailable($is_available);
            $this->userManager->updateUser($user);

            return $this->json(array(
                'new_label' => $is_available ? $this->translator->trans('form.switch.is_available.checked', [], 'form') : $this->translator->trans('form.switch.is_available.unchecked', [], 'form')
            ));
        } else {
            $response->setStatusCode(Response::HTTP_METHOD_NOT_ALLOWED);
        }

        return $response;
    }
}
