<?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\Response\Version3;

use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Sso\WebserviceBundle\EventListener\PerformanceListener;
use Sso\WebserviceBundle\Services\Application\All\ResponseBuilderInterface;
use Sso\WebserviceBundle\Services\Application\All\ResponseData\Applications as ApplicationData;
use Sso\WebserviceBundle\Services\ResponseBuilderInterface as GlobalResponseBuilderInterface;
use JMS\Serializer\SerializerInterface;

/**
 * Class ResponseBuilder
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Sso\WebserviceBundle\Services\Application\All\Response\Version3
 */
class ResponseBuilder implements ResponseBuilderInterface, GlobalResponseBuilderInterface
{
    /**
     * @var SerializerInterface
     */
    private $serializer;

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

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

    /**
     * @var PerformanceListener
     */
    private $performanceService;

    /**
     * @var ApplicationData
     */
    private $responseData;

    /**
     * ResponseBuilder constructor.
     * @param SerializerInterface $serializer
     * @param Factory $factory
     * @param ErrorHandlerInterface $errorHandler
     * @param PerformanceListener $performanceService
     */
    public function __construct(
        SerializerInterface $serializer,
        Factory $factory,
        ErrorHandlerInterface $errorHandler,
        PerformanceListener $performanceService
    ) {
        $this->serializer = $serializer;
        $this->factory = $factory;
        $this->errorHandler = $errorHandler;
        $this->performanceService = $performanceService;
    }

    /**
     * @return boolean
     */
    public function hasErrors()
    {
        return $this->errorHandler->hasErrors();
    }

    /**
     * @param string $format xml|json
     * @return string Response body
     */
    public function build($format)
    {
        $response = $this->errorHandler->hasErrors() ? $this->getErrorResponse() : $this->getSuccessResponse();
        return $this->serializer->serialize($response, $format);
    }

    /**
     * @return Response
     */
    private function getErrorResponse()
    {
        $response = $this->factory->response();
        $response->setErrors($this->errorHandler->getResponseObject());

        return $response;
    }

    /**
     * @return Response
     */
    private function getSuccessResponse()
    {
        $action = $this->factory->all();
        $action->setFullResponse($this->responseData->getFullResponse());
        $action->setStatus('Success');

        foreach ($this->responseData->getApplications() as $applicationData) {
            $applicationType = $this->factory->applicationType();
            $applicationType->setName((string)$applicationData->getName());
            foreach ($applicationData->getAttributeType() as $attributeData) {
                $attributeType = $this->factory->attributeType();
                $attributeType->setName((string)$attributeData->getName());
                $attributeType->setType((string)$attributeData->getType());
                $attributeType->setDisplayType($attributeData->getDisplayType());

                foreach ($attributeData->getAttributeOptions() ?? [] as $option) {
                    $attributeTypeOption = $this->factory->attributeTypeOption();
                    $attributeTypeOption->setLabel($option->getLabel());
                    $attributeTypeOption->setValue($option->getValue());
                    $attributeType->addAttributeTypeOption($attributeTypeOption);
                }

                $applicationType->addAttributeType($attributeType);
            }
            foreach ($applicationData->getApplicationRoleType() as $roleData) {
                $roleType = $this->factory->applicationRoleType();
                $roleType->setName((string)$roleData->getName());
                $roleType->setDescription((string)$roleData->getDescription());
                $applicationType->addApplicationRoleType($roleType);
            }
            $action->addApplication($applicationType);
        }

        $controller = $this->factory->application();
        $controller->setAll($action);

        $response = $this->factory->response();
        $response->setCode(200);
        $response->setStatus('Success');
        $response->setScriptTimeSec($this->performanceService->getScriptSeconds());
        $response->setApplication($controller);

        return $response;
    }

    /**
     * @param ApplicationData $applicationData
     */
    public function setResponse(ApplicationData $applicationData)
    {
        $this->responseData = $applicationData;
    }
}
