<?php

/**
 * Class FunctionsTest
 *
 * 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 LifeStyle\Tools\CachingBundle\Tests\Api\Data\Common;

use Symfony\Component\HttpFoundation\Request;
use LifeStyle\Tools\CachingBundle\Api\Data\Common;
use LifeStyle\Tools\CachingBundle\Annotations\LsCache;
use LifeStyle\Tools\CachingBundle\Api\Manager as ApiManager;
use PHPUnit_Framework_TestCase;

/**
 * Class FunctionsTest
 * @package LifeStyle\Tools\CachingBundle\Tests\Api\Data\Common
 */
class FunctionsTest extends PHPUnit_Framework_TestCase
{
    public function testCacheKeyGeneration()
    {
        $apiManagerMock = $this
            ->getMockBuilder(ApiManager::class)
            ->disableOriginalConstructor()
            ->getMock();
        $commonFactory = new Common\Factory($apiManagerMock);
        $functions = $commonFactory->functions();
        $lsCacheAnnotation = new LsCache([
            'CacheTTL' => 42,
            'KeyHeader' => true
        ]);
        $request = new Request();
        $request->headers->set('accept', '*/*');
        $request->headers->set('username', 'testuser');
        $request->headers->set('servicetoken', 'TEST00000');
        $request->headers->set('useridentifier', '24446666688888889');
        $request->query->set('param1', 'somevalue1');
        $request->query->set('param2', 'somevalue2');
        $request->attributes->set('_format', 'json');
        $request->attributes->set('_route', 'test_testroute_test');

        $cacheKey = 'test_testroute_test-e5a27e7f3d7e8b87bc493ef3ebdd577b';

        $this->assertEquals($cacheKey, $functions->generateCacheKey($request, $lsCacheAnnotation));

        $request->query->set('param2', 'somevalue3');
        $this->assertNotEquals($cacheKey, $functions->generateCacheKey($request, $lsCacheAnnotation));
        $request->query->set('param2', 'somevalue2');

        $request->headers->set('username', 'otheruser');
        $this->assertNotEquals($cacheKey, $functions->generateCacheKey($request, $lsCacheAnnotation));
        $request->headers->set('username', 'testuser');

        $request->attributes->set('_format', 'xml');
        $this->assertNotEquals($cacheKey, $functions->generateCacheKey($request, $lsCacheAnnotation));
        $request->attributes->set('_format', 'json');
    }


    public function testPostCacheKeyGeneration()
    {
        $apiManagerMock = $this
            ->getMockBuilder(ApiManager::class)
            ->disableOriginalConstructor()
            ->getMock();
        $commonFactory = new Common\Factory($apiManagerMock);
        $functions = $commonFactory->functions();
        $lsCacheAnnotation = new LsCache([
            'CacheTTL' => 42,
            'KeyHeader' => true
        ]);

        $request1 = Request::create('', 'POST', [], [], [], [], '{"value1":1337,"value2":"42"}');
        $request1->headers->set('accept', '*/*');
        $request1->headers->set('username', 'testuser');
        $request1->headers->set('servicetoken', 'TEST00000');
        $request1->headers->set('useridentifier', '24446666688888889');
        $request1->query->set('param1', 'somevalue1');
        $request1->query->set('param2', 'somevalue2');
        $request1->attributes->set('_format', 'json');
        $request1->attributes->set('_route', 'test_testroute_test');

        $request2 = Request::create('', 'POST', [], [], [], [], '{ "value1": 1337, "value2": "42" }');
        $request2->headers->set('accept', '*/*');
        $request2->headers->set('username', 'testuser');
        $request2->headers->set('servicetoken', 'TEST00000');
        $request2->headers->set('useridentifier', '24446666688888889');
        $request2->query->set('param1', 'somevalue1');
        $request2->query->set('param2', 'somevalue2');
        $request2->attributes->set('_format', 'json');
        $request2->attributes->set('_route', 'test_testroute_test');

        $request3 = Request::create('', 'POST', [], [], [], [], '{"value1":1337,"value2":"43"}');
        $request3->headers->set('accept', '*/*');
        $request3->headers->set('username', 'testuser');
        $request3->headers->set('servicetoken', 'TEST00000');
        $request3->headers->set('useridentifier', '24446666688888889');
        $request3->query->set('param1', 'somevalue1');
        $request3->query->set('param2', 'somevalue2');
        $request3->attributes->set('_format', 'json');
        $request3->attributes->set('_route', 'test_testroute_test');

        $cacheKey = 'test_testroute_test-0004d4870309da9aff624a737dff516f';

        $this->assertEquals($cacheKey, $functions->generateCacheKey($request1, $lsCacheAnnotation));
        $this->assertEquals($cacheKey, $functions->generateCacheKey($request2, $lsCacheAnnotation));
        $this->assertNotEquals($cacheKey, $functions->generateCacheKey($request3, $lsCacheAnnotation));
    }


    public function testStripWhitespace()
    {
        $apiManagerMock = $this
            ->getMockBuilder(ApiManager::class)
            ->disableOriginalConstructor()
            ->getMock();
        $commonFactory = new Common\Factory($apiManagerMock);
        $functions = $commonFactory->functions();

        $this->assertEquals($this->getWhitespaceExpectedXml(),
            $functions->stripWhitespace($this->getWhitespaceTestXml(), 'xml'));
        $this->assertEquals($this->getWhitespaceExpectedJson(),
            $functions->stripWhitespace($this->getWhitespaceTestJson(), 'json'));
        $someText = 'Some random text that should not be broken';
        $this->assertEquals($someText, $functions->stripWhitespace($someText));
    }

    private function getWhitespaceTestXml()
    {
        return '   <leadingWhitespace />
<test>
  <notherTest>
    <text>blah blah</text>
    <something /> <somethingElse />
    <someData><[CDATA[blah blah blah > blub < beep > < ]]></someData>
    <whiteData> </whiteData> <whiteData> </whiteData>
    <nothing></nothing>
    <dupe1>ABC</dupe1>
    <dupe2>ABC</dupe2>
  </notherTest>
</test>
<trailingWhitespace />    ';
    }

    private function getWhitespaceExpectedXml()
    {
        return '<leadingWhitespace/><test><notherTest><text>blah blah</text><something/><somethingElse/><someData><[CDATA[blah blah blah > blub < beep > < ]]></someData><whiteData> </whiteData><whiteData> </whiteData><nothing></nothing><dupe1>ABC</dupe1><dupe2>ABC</dupe2></notherTest></test><trailingWhitespace/>';
    }

    private function getWhitespaceTestJson()
    {
        return '    {
  "code": 200,
  "status": "OK",
  "test Type": {
    "testValue": "abc def ghi",
    "valueWithEscapedQuotes": "blah \"bleh\" blah",
    "active": 1,
    "deleted": 0
  },
  "applicationType": [
    {
      "name": "Test App",
      "active": 1
    }
  ]
}    ';
    }

    private function getWhitespaceExpectedJson()
    {
        return '{"code":200,"status":"OK","test Type":{"testValue":"abc def ghi","valueWithEscapedQuotes":"blah \"bleh\" blah","active":1,"deleted":0},"applicationType":[{"name":"Test App","active":1}]}';
    }
}
