<?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\WebserviceBundle\Services\Application\All;

use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Sso\WebserviceBundle\EventListener\PerformanceListener;
use Sso\WebserviceBundle\Security\Authorisation\ApplicationAuthorisation;
use Sso\WebserviceBundle\Services\Application\All\ResponseData\Factory;
use Sso\WebserviceBundle\Services\HandlerInterface;
use Sso\WebserviceBundle\Services\RequestInterface;
use Sso\WebserviceBundle\Services\ResponseBuilderInterface as ServicesResponseBuilderInterface;
use Sso\WebserviceBundle\Database\Webservice\Application as ApplicationRepository;
use Sso\WebserviceBundle\Entity\Webservice\Type\Application;

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

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

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

    /**
     * @var ApplicationRepository
     */
    private $database;

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

    /**
     * @var ApplicationAuthorisation
     */
    private $authorisation;

    /**
     * Handler constructor.
     * @param RequestParserInterface $requestParser
     * @param ResponseBuilderInterface|ServicesResponseBuilderInterface $responseBuilder
     * @param Factory $factory
     * @param ApplicationRepository $database
     * @param ErrorHandlerInterface $errorHandler
     * @param ApplicationAuthorisation $authorisation
     */
    public function __construct(
        RequestParserInterface $requestParser,
        $responseBuilder,
        Factory $factory,
        ApplicationRepository $database,
        ErrorHandlerInterface $errorHandler,
        ApplicationAuthorisation $authorisation
    ) {
        $this->requestParser = $requestParser;
        $this->responseBuilder = $responseBuilder;
        $this->factory = $factory;
        $this->database = $database;
        $this->errorHandler = $errorHandler;
        $this->authorisation = $authorisation;
    }

    /**
     * @param RequestInterface $request
     * @return ServicesResponseBuilderInterface
     * @throws \Exception
     */
    public function handle(RequestInterface $request)
    {
        $options = $this->requestParser->parse($request->getRequestBody());
        $authorisation = $this->authorisation;

        /** @var Application[] $applications */
        $applications = array_filter($this->database->getAllApplications(), function(Application $application) use ($authorisation) {
            return $authorisation->hasReadAccess($application->getName());
        });

        $applicationData = $this->factory->applications();
        $applicationData->setFullResponse($options->isFullResponse() ? 1 : 0);
        foreach ($applications as $application) {
            $applicationType = $this->factory->applicationType();
            $applicationType->setName((string)$application->getName());

            if ($options->isFullResponse()) {
                foreach ($application->getAttributes() as $attribute) {
                    $attributeType = $this->factory->attributeType();
                    $attributeType->setName((string)$attribute->getName());
                    $attributeType->setType((string)$attribute->getType());
                    $attributeType->setDisplayType((string)$attribute->getDisplayType());

                    foreach ($attribute->getAttributeOptions() ?? [] as $label => $value) {
                        $attributeTypeOption = $this->factory->attributeTypeOption();
                        $attributeTypeOption->setLabel($label);
                        $attributeTypeOption->setValue($value);
                        $attributeType->addAttributeOption($attributeTypeOption);
                    }

                    $applicationType->addAttributeType($attributeType);
                }
                foreach ($application->getRoles() as $role) {
                    $roleType = $this->factory->applicationRoleType();
                    $roleType->setName((string)$role->getName());
                    $roleType->setDescription((string)$role->getDescription());
                    $applicationType->addApplicationRoleType($roleType);
                }
            }

            $applicationData->addApplication($applicationType);
        }

        $this->responseBuilder->setResponse($applicationData);

        return $this->responseBuilder;
    }
}
