<?php

namespace KupShop\FeedGeneratorBundle\Tests;

use KupShop\FeedGeneratorBundle\Configuration\Configuration;
use KupShop\FeedGeneratorBundle\Configuration\Nodes\AttributeNode;
use KupShop\FeedGeneratorBundle\Configuration\Nodes\ConditionNode;
use KupShop\FeedGeneratorBundle\Configuration\Nodes\CycleNode;
use KupShop\FeedGeneratorBundle\Configuration\Nodes\ElementNode;
use KupShop\FeedGeneratorBundle\Configuration\Nodes\ExpressionNode;
use KupShop\FeedGeneratorBundle\Configuration\Nodes\ValueNode;
use KupShop\FeedGeneratorBundle\Configuration\NodesDenormalizer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

class NodesDenormalizerTest extends TestCase
{
    public function testJSONDeserialization()
    {
        $serializer = new Serializer(
            [
                new ObjectNormalizer(
                    null,
                    null,
                    null,
                    new ReflectionExtractor()
                ),
                new NodesDenormalizer(),
            ],
            [new JsonEncoder()]
        );

        $expressionNode = new ExpressionNode();
        $expressionNode->setType('expression');
        $expressionNode->setValue('some expression');
        $valueNode = new ValueNode();
        $valueNode->setType('value');
        $valueNode->setValue('some\'s value');
        $attributeNode = new AttributeNode();
        $attributeNode->setType('attribute');
        $attributeNode->setValue('some-attribute');
        $attributeNode->addNode($valueNode);
        $anotherValueNode = new ValueNode();
        $anotherValueNode->setType('value');
        $anotherValueNode->setValue('another value');
        $anotherAttributeNode = new AttributeNode();
        $anotherAttributeNode->setType('attribute');
        $anotherAttributeNode->setValue('another-attribute');
        $anotherAttributeNode->addNode($anotherValueNode);
        $firstNode = new ElementNode();
        $firstNode->setType('element');
        $firstNode->setValue('product');
        $firstNode->setNodes([$expressionNode, $attributeNode, $anotherAttributeNode]);
        $repeatedElementNode = new ElementNode();
        $repeatedElementNode->setType('element');
        $repeatedElementNode->setValue('some_repeated_element');
        $emptyConditionNode = new ConditionNode();
        $emptyConditionNode->setType('condition');
        $emptyConditionNode->setValue('');
        $emptyConditionNode->setNodes([$repeatedElementNode]);
        $cycleNode = new CycleNode();
        $cycleNode->setType('cycle');
        $cycleNode->setValue('parameters');
        $cycleNode->setValueAccessName('params');
        $cycleNode->setNodes([$emptyConditionNode]);
        $secondNode = new ConditionNode();
        $secondNode->setType('condition');
        $secondNode->setValue('some condition');
        $secondNode->setNodes([$cycleNode]);
        $configuration = new Configuration();
        $configuration->setBeginning('<?xml version="1.0" encoding="utf-8"?>'.PHP_EOL.'<catalog>');
        $configuration->setEnd('</catalog>');
        $configuration->addNode($firstNode);
        $configuration->addNode($secondNode);

        $jsonString = file_get_contents(__DIR__.'/NodesDenormalizerData.json');
        $actualConfiguration = $serializer->deserialize(
            $jsonString,
            Configuration::class,
            'json'
        );

        $configurationAsReadableString = print_r($configuration, true);
        $actualConfigurationAsReadableString = print_r($actualConfiguration, true);

        $this->assertEquals(
            $configurationAsReadableString,
            $actualConfigurationAsReadableString,
            'Deserialized JSON configuration does not match!'
        );
    }
}
