<?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\PasswordPolicy\Show\Response\Version2;

use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Sso\WebserviceBundle\Services\PasswordPolicy\Show\ResponseBuilderInterface;
use Sso\WebserviceBundle\Services\ResponseBuilderInterface as GlobalResponseBuilderInterface;
use Sso\WebserviceBundle\Services\PasswordPolicy\Show\ResponseData\PasswordPolicy;
use JMS\Serializer\SerializerInterface;
use Sso\WebserviceBundle\Services\PasswordPolicy\Show\ResponseData\PasswordPolicy as PasswordPolicyData;

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

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

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

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

    /**
     * @var array
     */
    private $userTypeMapping = array(
        'getGuid' => 'guid',
        'getEmail' => 'email',
        'getUsername' => 'username',
        'getFirstname' => 'firstname',
        'getLastname' => 'lastname'
    );

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

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

    /**
     * @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());
        $response->setTrackid(null);
        $response->setDate(null);

        return $response;
    }

    /**
     * @return Response
     */
    private function getSuccessResponse()
    {
        $userType = $this->factory->userType();
        $userType->setFromArray($this->mapUserType($this->responseData));

        //map policy
        $passwordPolicyType = $this->mapPasswordPolicyType($this->responseData);


        $show = $this->factory->show();
        $show->setUserType($userType);
        $show->setPasswordPolicyType($passwordPolicyType);
        $show->setStatus('Success');
        $user = $this->factory->passwordPolicy();

        $user->addShow($show);

        $response = $this->factory->response();
        $response->setCode(200);
        $response->setScriptTimeSec($this->factory->scriptTimeSeconds());
        $response->setPasswordPolicy($user);

        return $response;
    }

    /**
     * @param PasswordPolicyData $data
     * @return array
     */
    private function mapUserType(PasswordPolicyData $data)
    {
        $userType = array();
        foreach ($this->userTypeMapping as $getter => $attributeName) {
            $userType[$attributeName] = $data->$getter();
        }
        return $userType;
    }

    /**
     * @param PasswordPolicyData $data
     * @return PasswordPolicyType
     */
    private function mapPasswordPolicyType(PasswordPolicyData $data)
    {
        $passwordPolicyType = $this->factory->passwordPolicyType();

        if (!empty($data->getPolicyId())) {
            $passwordPolicyType->setPolicyId($data->getPolicyId());
        }

        if (!empty($data->getTitle())) {
            $passwordPolicyType->setTitle($data->getTitle());
        }

        if (!empty($data->getRegEx())) {
            $passwordPolicyType->setRegEx($data->getRegEx());
        }

        if (!empty($data->getRegexErrorMessages() && is_array($data->getRegexErrorMessages()))) {
            foreach ($data->getRegexErrorMessages() as $lang => $message) {
                $transType = $this->factory->translationType();
                $transType->setLanguage($lang);
                $transType->setMessage($message);
                $passwordPolicyType->addRegexErrorMessages($transType);
            }
        }

        if (!empty($data->getValidityDuration())) {
            $passwordPolicyType->setValidityDuration($data->getValidityDuration());
        }

        if (!empty($data->getValidityDurationErrorMessages() && is_array($data->getValidityDurationErrorMessages()))) {
            foreach ($data->getValidityDurationErrorMessages() as $lang => $message) {
                $transType = $this->factory->translationType();
                $transType->setLanguage($lang);
                $transType->setMessage($message);
                $passwordPolicyType->addValidityDurationErrorMessages($transType);
            }
        }

        if (!empty($data->getHistorySize())) {
            $passwordPolicyType->setHistorySize($data->getHistorySize());
        }

        if (!empty($data->getHistorySizeErrorMessages() && is_array($data->getHistorySizeErrorMessages()))) {
            foreach ($data->getHistorySizeErrorMessages() as $lang => $message) {
                $transType = $this->factory->translationType();
                $transType->setLanguage($lang);
                $transType->setMessage($message);
                $passwordPolicyType->addHistorySizeErrorMessages($transType);
            }
        }

        if (!empty($data->getEditDistance())) {
            $passwordPolicyType->setEditDistance($data->getEditDistance());
        }

        if (!empty($data->getEditDistanceErrorMessages() && is_array($data->getEditDistanceErrorMessages()))) {
            foreach ($data->getEditDistanceErrorMessages() as $lang => $message) {
                $transType = $this->factory->translationType();
                $transType->setLanguage($lang);
                $transType->setMessage($message);
                $passwordPolicyType->addEditDistanceErrorMessages($transType);
            }
        }

        if (!empty($data->getChangeDelay())) {
            $passwordPolicyType->setChangeDelay($data->getChangeDelay());
        }

        if (!empty($data->getChangeDelayErrorMessages() && is_array($data->getChangeDelayErrorMessages()))) {
            foreach ($data->getChangeDelayErrorMessages() as $lang => $message) {
                $transType = $this->factory->translationType();
                $transType->setLanguage($lang);
                $transType->setMessage($message);
                $passwordPolicyType->addChangeDelayErrorMessages($transType);
            }
        }

        if (!empty($data->getPolicyDescription())) {
            $passwordPolicyType->setPolicyDescription($data->getPolicyDescription());
        }

        if (!empty($data->getErrorMessages() && is_array($data->getErrorMessages()))) {
            foreach ($data->getErrorMessages() as $lang => $message) {
                $transType = $this->factory->translationType();
                $transType->setLanguage($lang);
                $transType->setMessage($message);
                $passwordPolicyType->addErrorMessages($transType);
            }
        }

        if (!empty($data->isDefault())) {
            $passwordPolicyType->setIsDefault($data->isDefault() ? true : false);
        }

        return $passwordPolicyType;
    }
}
