<?php

/**
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is protected 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  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Sso\RestBundle\Tests\ModelXml\Response\ObjectWs\Version1\Attribute\Update;

use Sso\RestBundle\Api;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Error\Error;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Success\AttributeType;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Success\Update as SuccessUpdate;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Success\Response as SuccessXmlResponse;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Success\Attribute as SuccessAttribute;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Error\Update as ErrorUpdate;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Error\Response as ErrorXmlResponse;
use Sso\RestBundle\ModelXml\Response\ObjectWs\Version1\Attribute\Update\Error\Attribute as ErrorAttribute;
use GuzzleHttp\Client;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Faker\Factory as FakerFactory;
use Faker\Generator as FakerGenerator;

/**
 * Class ResponseTest
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */
class ResponseTest extends WebTestCase
{
    /**
     * @var Api\Manager
     */
    public $apiM;

    /**
     * @var Client
     */
    protected $client;

    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var \JMS\Serializer\Serializer
     */
    protected $serializer;

    /**
     * @var FakerGenerator
     */
    private $faker;

    /**
     * @var float
     */
    private $scriptTimeSec;

    /**
     * @var string
     */
    private $trackId;

    /**
     * @var string
     */
    private $date;

    /**
     * @var string
     */
    private $message;

    /**
     * @var string
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * @var int
     */
    private $mandatory;

    /**
     * @var string
     */
    private $possibleValue;

    /**
     * @var string
     */
    private $defaultValue;

    /**
     * @var int
     */
    private $translatable;

    /**
     * @var string
     */
    private $groupId;


    protected function setUp()
    {
        $this->client = static::createClient();
        $this->container = $this->client->getContainer();
        $this->apiM = new Api\Manager($this->container);
        $this->serializer = $this->apiM->serializer();
        $this->faker = FakerFactory::create();

        // Set same random data
        $this->scriptTimeSec = $this->faker->randomFloat(2);
        $this->trackId = $this->faker->md5;
        $this->date = '2099-01-01T00:00:00+00:00';
        $this->message = $this->faker->sentence(2);
        $this->id = $this->faker->sha1;
        $this->name = $this->faker->name;
        $this->mandatory = $this->faker->boolean ? 1 : 0;
        $this->possibleValue = $this->faker->word;
        $this->defaultValue = $this->faker->word;
        $this->translatable = $this->faker->boolean ? 1 : 0;
        $this->groupId = $this->faker->sha1;
    }

    public function testSuccessResponseModel()
    {
        $this->assertXmlStringEqualsXmlString($this->getSuccessResponse(), $this->getSuccessResponseModel());
    }

    public function testErrorResponseModel()
    {
        $this->assertXmlStringEqualsXmlString($this->getErrorResponse(), $this->getErrorResponseModel());
    }

    private function getSuccessResponseModel()
    {
        $response = new SuccessXmlResponse();
        $response->setStatus('OK');
        $response->setTrackId($this->trackId);
        $response->setDate(new \DateTime($this->date));

        $attribute = new SuccessAttribute();
        $update = new SuccessUpdate();
        $attributeType = new AttributeType();

        $attributeType
            ->setId($this->id)
            ->setName($this->name)
            ->setMandatory($this->mandatory)
            ->setPossibleValues([$this->possibleValue])
            ->setDefaultValue($this->defaultValue)
            ->setTranslatable($this->translatable)
            ->setGroupId($this->groupId);

        $update
            ->setStatus('OK')
            ->setAttributeType($attributeType);

        $attribute->setUpdate($update);

        $response->setAttribute($attribute);

        $responseModel = $this->serializer->serialize($response, 'xml');

        return $responseModel;
    }

    private function getErrorResponseModel()
    {
        $response = new ErrorXmlResponse();
        $response->setStatus('Failure');
        $response->setTrackId($this->trackId);
        $response->setDate(new \DateTime($this->date));

        $attribute = new ErrorAttribute();
        $update = new ErrorUpdate();
        $error = new Error();

        $error->setErrorCode('fw003');
        $error->setErrorRef('hd007');
        $error->setShortMessage('InvalidXml');
        $error->setLongMessage($this->message);

        $update->setStatus('Failure')->setError($error);
        $attribute->setUpdate($update);

        $response->setAttribute($attribute);

        $responseModel = $this->serializer->serialize($response, 'xml');

        return $responseModel;
    }

    /**
     * @return string
     */
    private function getSuccessResponse()
    {
        return '<?xml version="1.0" encoding="utf-8"?>
            <SsoResponse>
                <Status><![CDATA[OK]]></Status>
                <Trackid><![CDATA[' . $this->trackId . ']]></Trackid>
                <Date><![CDATA[' . $this->date . ']]></Date>
                <Attribute>
                    <Update>
                        <Status><![CDATA[OK]]></Status>
                        <AttributeType>
                            <Id><![CDATA[' . $this->id . ']]></Id>
                            <Name><![CDATA[' . $this->name . ']]></Name>
                            <Mandatory>' . $this->mandatory . '</Mandatory>
                            <PossibleValues>
                                <Value><![CDATA[' . $this->possibleValue . ']]></Value>                        
                            </PossibleValues>
                            <DefaultValue><![CDATA[' . $this->defaultValue . ']]></DefaultValue>
                            <Translatable>' . $this->translatable . '</Translatable>
                            <GroupId><![CDATA[' . $this->groupId . ']]></GroupId>
                        </AttributeType>
                    </Update>
                </Attribute>
            </SsoResponse>';
    }

    /**
     * @return string
     */
    private function getErrorResponse()
    {
        return '<?xml version="1.0" encoding="utf-8"?>
            <SsoResponse>
                <Status><![CDATA[Failure]]></Status>
                <Trackid><![CDATA[' . $this->trackId . ']]></Trackid>
                <Date><![CDATA[' . $this->date . ']]></Date>
                <Attribute>
                    <Update>
                        <Status><![CDATA[Failure]]></Status>
                        <Errors>
                            <Error>
                                <ErrorCode><![CDATA[fw003]]></ErrorCode>
                                <ErrorRef><![CDATA[hd007]]></ErrorRef>
                                <ShortMessage><![CDATA[InvalidXml]]></ShortMessage>
                                <LongMessage><![CDATA[' . $this->message . ']]></LongMessage>    
                            </Error>
                        </Errors>
                    </Update>
                </Attribute>
            </SsoResponse>';
    }

    public function testSuccessGetters()
    {
        /** @var SuccessXmlResponse $responseModel */
        $responseModel = $this->serializer->deserialize(
            $this->getSuccessResponseModel(),
            SuccessXmlResponse::class,
            'xml'
        );

        $this->assertEquals('OK', $responseModel->getStatus());
        $this->assertEquals($this->trackId, $responseModel->getTrackId());
        $this->assertEquals(new \DateTime($this->date), $responseModel->getDate());
        $this->assertEquals('OK', $responseModel->getAttribute()->getUpdate()->getStatus());
        $this->assertEquals($this->id, $responseModel->getAttribute()->getUpdate()->getAttributeType()->getId());
        $this->assertEquals($this->name, $responseModel->getAttribute()->getUpdate()->getAttributeType()->getName());
        $this->assertEquals($this->mandatory,
            $responseModel->getAttribute()->getUpdate()->getAttributeType()->getMandatory());
        $this->assertEquals($this->possibleValue,
            $responseModel->getAttribute()->getUpdate()->getAttributeType()->getPossibleValues()[0]);
        $this->assertEquals($this->defaultValue,
            $responseModel->getAttribute()->getUpdate()->getAttributeType()->getDefaultValue());
        $this->assertEquals($this->translatable,
            $responseModel->getAttribute()->getUpdate()->getAttributeType()->getTranslatable());
        $this->assertEquals($this->groupId,
            $responseModel->getAttribute()->getUpdate()->getAttributeType()->getGroupId());
    }

    public function testErrorGetters()
    {
        /** @var ErrorXmlResponse $responseModel */
        $responseModel = $this->serializer->deserialize(
            $this->getErrorResponseModel(),
            ErrorXmlResponse::class,
            'xml'
        );

        $error = $responseModel->getAttribute()->getUpdate()->getErrors()->get(0);

        $this->assertEquals('Failure', $responseModel->getStatus());
        $this->assertEquals($this->trackId, $responseModel->getTrackId());
        $this->assertEquals(new \DateTime($this->date), $responseModel->getDate());
        $this->assertEquals('Failure', $responseModel->getAttribute()->getUpdate()->getStatus());
        $this->assertEquals('fw003', $error->getErrorCode());
        $this->assertEquals('hd007', $error->getErrorRef());
        $this->assertEquals('InvalidXml', $error->getShortMessage());
        $this->assertEquals($this->message, $error->getLongMessage());
    }
}
