<?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\UserWs\Version2\UserApplication\ShowDetails\Utils;

use FOS\RestBundle\View\View as RestView;
use Sso\RestBundle\Api\Manager as ApiManager;
use LifeStyle\Tools\RestErrorBundle\Api\Manager as ErrorApi;
use LifeStyle\Tools\RestErrorBundle\Api\Error\Errors\Index as Errors;
use Sso\RestBundle\ModelRest\Response\UserWs\Version2\UserApplication\ShowDetails\Factory as ResponseModel;
use Sso\RestBundle\Api\Helper\Mapper\Index as Mapper;
use Sso\RestBundle\ModelXml\Response\UserWs\Version2\UserApplication\ShowDetails\Error\Response as XmlError;
use Sso\RestBundle\ModelXml\Response\UserWs\Version2\UserApplication\ShowDetails\Success\Response as XmlSuccess;

class Index
{

    const STATUS = "status";
    const ERROR_EXTERNAL = "external";


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


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

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

    /**
     * @var XmlError
     */
    private $xmlError;

    /**
     * @var XmlSuccess
     */
    private $xmlSuccess;

    /**
     * @var ResponseModel
     */
    private $responseModel;

    /**
     * @var Mapper
     */
    private $mapper;

    /**
     * @param ApiManager $apiM
     */
    public function __construct(ApiManager $apiM)
    {
        $this->apiM = $apiM;
        $this->errorApi = $this->apiM->errorManager();
        $this->errors = $this->errorApi->error()->errors();
        $this->mapper = $this->apiM->helper()->mapper();
        $this->responseModel = $this->apiM->modelRest()->response()->userWs()->version2()->userApplication()->showDetails();
    }


    /**
     * @param $xmlResponse
     * @return RestView $view
     */
    public function buildItem($xmlResponse)
    {
        $view = RestView::create();
        if (!$xmlResponse[static::STATUS]) {
            // build error response for item
            $view = $this->buildError($xmlResponse['xml'], $view);
        } else {
            // fill the success response for item
            $view = $this->buildSuccess($xmlResponse['xml'], $view);
        }
        return $view;
    }

    /**
     * @param $xmlString
     * @param RestView $view
     * @return RestView $responseItem
     */
    private function buildSuccess($xmlString, RestView $view)
    {
        $this->xmlSuccess = $this->apiM->serializer()->deserialize($xmlString, XmlSuccess::class, 'xml');

        if ($this->xmlSuccess->getCode() != 200) {
            return $this->buildError($xmlString, $view);
        }

        $responseItem = $this->responseModel->success()->response();

        $responseItem->setCode($this->xmlSuccess->getCode());
        $responseItem->setTrackId($this->xmlSuccess->getTrackid());
        $responseItem->setStatus($this->xmlSuccess->getStatus());
        $responseItem->setScriptTimeSec($this->apiM->scriptTimeSeconds());

        //map userType Model
        $xmlUserType = $this->xmlSuccess->getUserApplication()->getShowDetails()->getUserType();
        $mappedModelUserType = $this->mapper->modelInToModelOut($xmlUserType,
            $this->responseModel->success()->userType());
        $responseItem->setUserType($mappedModelUserType);

        $responseItemBody = $this->buildSuccessApplicationType($responseItem);

        $view->setData($responseItemBody)->setStatusCode(200);

        return $view;
    }


    /**
     * @param $responseItem
     * @return mixed
     */
    private function buildSuccessApplicationType($responseItem)
    {

        //map applicationType Model
        foreach ($this->xmlSuccess->getUserApplication()->getShowDetails()->getApplicationType() as $xmlApplicationType) {
            $applicationType = $this->responseModel->success()->applicationType();
            $applicationType = $this->mapper->modelInToModelOut($xmlApplicationType, $applicationType);

            foreach ($xmlApplicationType->getAttributeType() as $xmlAttributeType) {

                $attributeType = $this->responseModel->success()->attributeType();
                $attributeType = $this->mapper->modelInToModelOut($xmlAttributeType, $attributeType);
                $applicationType->addAttributeType($attributeType);
            }

            foreach ($xmlApplicationType->getApplicationRoleType() as $xmlApplicationRoleType) {
                $applicationRoleType = $this->responseModel->success()->applicationRoleType();
                $applicationRoleType = $this->mapper->modelInToModelOut($xmlApplicationRoleType, $applicationRoleType);
                $applicationType->addApplicationRoleType($applicationRoleType);
            }

            $responseItem->addApplicationType($applicationType);
        }

        return $responseItem;
    }

    /**
     * @param $xmlString
     * @param Restview $view
     * @return RestView $responseItem
     */
    private function buildError($xmlString, RestView $view)
    {

        $responseItem = $this->responseModel->error()->response();
        $this->xmlError = $this->apiM->serializer()->deserialize($xmlString, XmlError::class, 'xml');

        $errors = $this->xmlError->getErrors();

        foreach ($errors as $error) {
            $errorItem = $this->apiM->modelRest()->response()->userWs()->version2()->userApplication()->showDetails()->error()->error();
            $message = 'ErrorCode: ' . $error->getErrorCode() . ' ErrorRef: ' . $error->getErrorRef() . ' ShortMessage: ' . $error->getShortMessage();
            $errorItem->setMessage($message);
            $errorItem->setCode(400);
            $errorItem->setException(static::ERROR_EXTERNAL);
            $responseItem->setError($errorItem);
        }

        // Add additional fields to response
        $responseItem
            ->setCode($this->xmlError->getCode())
            ->setTrackId($this->xmlError->getTrackId())
            ->setDate($this->xmlError->getDate())
            ->setScriptTimeSec($this->apiM->scriptTimeSeconds());

        return $view->setData($responseItem)->setStatusCode($this->xmlError->getCode());
    }
}
