<?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  2019 Lifestyle Webconsulting GmbH
 * @link       https://www.life-style.de
 */

namespace Sso\WebserviceBundle\Services\ApplicationAttribute\Show;

use Sso\WebserviceBundle\Api\Exception\Type\Api;
use Sso\WebserviceBundle\Api\Exception\Type\Api as ApiException;
use Sso\WebserviceBundle\Database\Webservice\Application as ApplicationDatabase;
use Sso\WebserviceBundle\Database\Webservice\Attribute as AttributeDatabase;
use Sso\WebserviceBundle\Entity\Webservice\Type\Application as ApplicationEntity;
use Sso\WebserviceBundle\Entity\Webservice\Type\Attribute;
use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Sso\WebserviceBundle\Exception\InvalidRequestException;
use Sso\WebserviceBundle\Services\ApplicationAttribute\Show\ResponseData\Factory;
use Sso\WebserviceBundle\Services\HandlerInterface;
use Sso\WebserviceBundle\Services\RequestInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
 * Class Handler
 *
 * @copyright  2019 Lifestyle Webconsulting GmbH
 * @link       https://www.life-style.de
 * @package Sso\WebserviceBundle\Services\ApplicationAttribute\Show
 */
class Handler implements HandlerInterface
{
    /**
     * @var RequestParserInterface
     */
    private $requestParser;

    /**
     * @var ResponseBuilderInterface
     */
    private $responseBuilder;

    /**
     * @var ErrorHandlerInterface
     */
    private $errorHandler;

    /**
     * @var Factory
     */
    private $factory;

    /**
     * @var ApplicationDatabase
     */
    private $applicationDatabase;

    /**
     * @var AttributeDatabase
     */
    private $attributeDatabase;

    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * Handler constructor.
     * @param RequestParserInterface $requestParser
     * @param ResponseBuilderInterface $responseBuilder
     * @param ErrorHandlerInterface $errorHandler
     * @param Factory $factory
     * @param ApplicationDatabase $applicationDatabase
     * @param AttributeDatabase $attributeDatabase
     * @param ValidatorInterface $validator
     */
    public function __construct(
        RequestParserInterface $requestParser,
        ResponseBuilderInterface $responseBuilder,
        ErrorHandlerInterface $errorHandler,
        Factory $factory,
        ApplicationDatabase $applicationDatabase,
        AttributeDatabase $attributeDatabase,
        ValidatorInterface $validator
    ) {
        $this->requestParser = $requestParser;
        $this->responseBuilder = $responseBuilder;
        $this->errorHandler = $errorHandler;
        $this->factory = $factory;
        $this->applicationDatabase = $applicationDatabase;
        $this->attributeDatabase = $attributeDatabase;
        $this->validator = $validator;
    }

    /**
     * @param RequestInterface $request
     * @return ResponseBuilderInterface
     */
    public function handle(RequestInterface $request)
    {
        try {
            $requestData = $this->parseRequest($request);
            $application = $this->findApplication($requestData);
            $attribute = $this->findAttribute($application, $requestData);
            $this->setResponseData($attribute);
        } catch (InvalidRequestException $exception) {
            unset($exception);
        }

        return $this->responseBuilder;
    }

    /**
     * @param RequestData\ApplicationAttributeData $requestData
     * @return ApplicationEntity|null
     * @throws InvalidRequestException
     */
    private function findApplication(RequestData\ApplicationAttributeData $requestData)
    {
        $application = $this->applicationDatabase->getApplicationByName(
            $requestData->getApplicationName()
        );
        if (null === $application) {
            $this->errorHandler->addError(404, 'ApplicationNotFound', 'ats2001', '', '');
            throw new InvalidRequestException();
        }
        return $application;
    }

    /**
     * @param ApplicationEntity $application
     * @param RequestData\ApplicationAttributeData $requestData
     * @return Attribute|null
     * @throws InvalidRequestException
     */
    private function findAttribute(
        ApplicationEntity $application,
        RequestData\ApplicationAttributeData $requestData
    ) {
        $attribute = $this->attributeDatabase->getAttributeByName(
            $application,
            $requestData->getAttributeName()
        );

        if (null === $attribute) {
            $this->errorHandler->addError(404, 'ApplicationAttributeNotFound', 'ats2002', '', '');
            throw new InvalidRequestException();
        }
        return $attribute;
    }

    /**
     * @param Attribute|null $attribute
     */
    private function setResponseData(?Attribute $attribute): void
    {
        $responseData = $this->factory->applicationAttributeData();
        $responseData->setAttributeName($attribute->getName());
        $responseData->setAttributeType($attribute->getType());
        $responseData->setAttributeDisplayType($attribute->getDisplayType());
        $responseData->setAttributeOptions($attribute->getAttributeOptions());
        $this->responseBuilder->setResponse($responseData);
    }

    /**
     * @param RequestInterface $request
     * @return RequestData\ApplicationAttributeData
     * @throws InvalidRequestException
     */
    private function parseRequest(RequestInterface $request): RequestData\ApplicationAttributeData
    {
        $requestData = $this->requestParser->parse($request->getRequestBody());
        if ($this->errorHandler->hasErrors()) {
            throw new InvalidRequestException();
        }
        return $requestData;
    }
}
