<?php

namespace NPS\EventSubscriber;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use NPS\Exception\UserInputException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Global exception listener
 * Should transcribe all errors into json format
 * @author Lukas Korinek
 */
class ExceptionSubscriber implements EventSubscriberInterface
{

    /**
     * @inheritdoc
     */
    public static function getSubscribedEvents()
    {
        return ['kernel.exception' => 'onKernelException'];
    }

    /**
     * Kernel exception handler
     * @param GetResponseForExceptionEvent $event
     */
    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();

        if($exception instanceof UserInputException)
        {
            $response = $this->userInputError($exception);
        }
        else if($exception instanceof MethodNotAllowedException || $exception instanceof RouteNotFoundException || $exception instanceof MethodNotAllowedHttpException || $exception instanceof NotFoundHttpException)
        {
            $response = $this->notFoundError($exception);
        }
        else
        {
            $response = $this->internalServerError($exception);
        }

        $event->setResponse($response);
    }

    /**
     * Creates an internal server error response and payload
     * @param \Exception $exception 
     * @return JsonResponse
     */
    private function internalServerError(\Exception $exception)
    {
        return new JsonResponse([
            'message' => json_encode($exception->getMessage()),
            'line' => $exception->getLine(),
            'file' => $exception->getFile(),
            'trace' => $exception->getTrace(),
            'debug' => isset($GLOBALS['debug']) ? $GLOBALS['debug'] : []
        ], 500);
    }

    /**
     * Creates a not found error
     * @param \Exception $exception 
     * @return JsonResponse
     */
    private function notFoundError(\Exception $exception)
    {
        return new JsonResponse([
            'message' => json_encode($exception->getMessage()),
            //'line' => $exception->getLine(),
            //'file' => $exception->getFile(),
            //'trace' => $exception->getTrace(),
            'debug' => isset($GLOBALS['debug']) ? $GLOBALS['debug'] : []
        ], 404);
    }

    /**
     * Creates user input error response and payload
     * @param \NPS\Exception\UserInputException $exception 
     * @return JsonResponse
     */
    private function userInputError(\NPS\Exception\UserInputException $exception)
    {
        return new JsonResponse([
            'message' => json_encode($exception->getMessage()),
            'subject' => $exception->getSubject(),
            'line' => $exception->getLine(),
            'file' => $exception->getFile(),
            'debug' => isset($GLOBALS['debug']) ? $GLOBALS['debug'] : []
        ], 400);
    }

}

