<?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\RestBundle\Worker\ObjectWs\Version1\ObjectType\Update\Utils\ObjectTypeUpdate;

use Sso\RestBundle\Api\Manager as ApiManager;
use Sso\RestBundle\ModelRest\Request\ObjectWs\Version1\ObjectType\Update\Request as RequestModel;
use LifeStyle\Tools\RestAuthBundle\Security\Authentication\Token\UidentifyToken;
use Sso\RestBundle\ModelRest\Request\ObjectWs\Version1\ObjectType\Update\Item as RequestItem;
use Sso\RestBundle\ModelRest\Response\ObjectWS\Version1\ObjectType\Update\Item as ResponseItem;
use GuzzleHttp\Exception\RequestException;

/**
 * Class Index
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package    Sso\RestBundle\Worker\ObjectWs\Version1\ObjectType\UpdateObjectType\Utils\ObjectTypeUpdate
 */
class Index
{
    /**
     * @var UidentifyToken
     */
    protected $userToken;

    /**
     *
     * @var ApiManager
     */
    protected $apiM;

    /**
     *
     * @var ErrorApi
     */
    protected $errorApi;

    /**
     *
     * @var Errors
     */
    protected $errors;

    /**
     *
     * @var \Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\ObjectType\Update\ObjectTypeUpdate\Error\Response
     */
    protected $errorXmlEntity;

    /**
     *
     * @var \Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\ObjectType\Update\ObjectTypeUpdate\Success\Response
     */
    protected $successXmlEntity;


    /**
     *
     * @param ApiManager $apiM
     */
    public function __construct(ApiManager $apiM)
    {
        $this->apiM = $apiM;
        $this->userToken = $this->apiM->getToken();
    }


    /**
     * @param RequestItem $item
     * @return ResponseItem
     */
    public function send(RequestItem $item)
    {

        $requestModelXml = $this->apiM->modelXml()->request()->objectWs()->version1()->objectType()->update()->objectTypeUpdate()->request();

        // add credentials
        $credentialsModelXml = $this->apiM->modelXml()->request()->objectWs()->version1()->objectType()->update()->objectTypeUpdate()->credentials();
        $credentialsModelXml->setCredentialsData($this->userToken->servicetoken, 'ObjectTypeUpdate',
            $this->userToken->useridentifier, $this->userToken->username, 'en');
        $requestModelXml->setCredentials($credentialsModelXml);

        // add objectType
        $objectModelXml = $this->apiM->modelXml()->request()->objectWs()->version1()->objectType()->update()->objectTypeUpdate()->objectType();
        $objectModelXml->setObjectTypeData($item->getId(), $item->getName(), $item->getOrder());
        $requestModelXml->setObjectType($objectModelXml);

        $options = array(
            'headers' => array(
                'API-VERSION' => '1',
                'API-CONTROLLER' => 'Type',
                'API-ACTION' => 'Update',
                'Content-Type' => 'text/xml; charset=UTF-8',
            ),
            'body' => $this->apiM->serializer()->serialize($requestModelXml, 'xml'),
        );

        try {
            $clientResponse = $this->apiM->client()->post($this->apiM->configuration()->objectWs()->getBaseUrl() . $this->apiM->configuration()->objectWs()->getServiceAction(),
                $options);
        } catch (RequestException $ex) {
            $errorResponse = $ex->getResponse()->getBody()->getContents();
            $this->apiM->logger()->error($errorResponse);
            return $this->buildItem(['status' => false, 'xml' => $errorResponse], $item);
        }

        return $this->buildItem(['status' => true, 'xml' => $clientResponse->getBody()->getContents()], $item);
    }

    /**
     *
     * @param string $xmlResponse
     * @param RequestItem $item
     * @return ResponseItem
     */
    private function buildItem($xmlResponse, RequestItem $item)
    {
        $responseItem = $this->apiM->modelRest()->response()->objectWs()->version1()->objectType()->update()->item();
        $responseItem = $this->apiM->helper()->mapper()->modelInToModelOut($item, $responseItem);

        if (!$xmlResponse['status']) {
            // build error response for item
            $responseItem = $this->buildError($xmlResponse['xml'], $responseItem);
        } else {
            // fill the success response for item
            $responseItem = $this->buildSuccess($xmlResponse['xml'], $responseItem);
        }

        return $responseItem;
    }

    /**
     *
     * @param string $xmlString
     * @param ResponseItem $responseItem
     * @return ResponseItem
     */
    private function buildSuccess($xmlString, ResponseItem $responseItem)
    {
        $responseItem->setCode(200);
        $this->successXmlEntity = $this->apiM->serializer()->deserialize($xmlString,
            'Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\ObjectType\Update\ObjectTypeUpdate\Success\Response',
            'xml');
        $responseItem->setName($this->successXmlEntity->getType()->getUpdate()->getTypeType()->getName());
        $responseItem->setOrder($this->successXmlEntity->getType()->getUpdate()->getTypeType()->getOrder());
        $responseItem->setCreated($this->successXmlEntity->getType()->getUpdate()->getTypeType()->getCreated());
        $responseItem->setUpdated($this->successXmlEntity->getType()->getUpdate()->getTypeType()->getUpdated());
        $responseItem->setScriptTimeSec($this->apiM->scriptTimeSeconds());

        return $responseItem;
    }

    /**
     *
     * @param string $xmlString
     * @param ResponseItem $responseItem
     * @return ResponseItem
     */
    private function buildError($xmlString, ResponseItem $responseItem)
    {
        $errorsItem = $this->apiM->modelRest()->response()->objectWs()->version1()->objectType()->update()->errors();
        $responseItem->setCode(400);
        $this->errorXmlEntity = $this->apiM->serializer()->deserialize($xmlString,
            'Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\ObjectType\Update\ObjectTypeUpdate\Error\Response',
            'xml');
        $errorsItem->setTrackId($this->errorXmlEntity->getTrackid());
        $errorsItem->setCode(400);
        $errors = $this->errorXmlEntity->getType()->getUpdate()->getError();

        foreach ($errors as $error) {
            $errorItem = $this->apiM->modelRest()->response()->objectWs()->version1()->objectType()->update()->error();
            $message = 'ErrorCode: ' . $error->getErrorCode() . ' ErrorRef: ' . $error->getErrorRef() . ' ShortMessage: ' . $error->getShortMessage();
            $errorItem->setMessage($message);
            $errorItem->setCode(400);
            $errorItem->setException('external');
            $errorsItem->addError($errorItem);
        }
        $responseItem->setScriptTimeSec($this->apiM->scriptTimeSeconds());
        $responseItem->setErrors($errorsItem);

        return $responseItem;
    }
}