<?php namespace MapGuesser\Tests\View\Parser;

use MapGuesser\View\ParsedFragment;
use MapGuesser\View\Parser;
use PHPUnit\Framework\TestCase;

final class ParserTest extends TestCase
{
    const TEST_VIEWS_PATH = __DIR__ . '/../../views/tests';

    public function testCanParseViewWithoutExtends(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_without_extends.php');

        $parser = new Parser($file);
        $fragment = $parser->parse();

        $expected = new ParsedFragment(
            null,
            [],
            [],
            [],
            ['', '']
        );

        $this->assertEquals($expected, $fragment);
    }

    public function testCanParseViewWithAssets(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_with_assets.php');

        $parser = new Parser($file);
        $fragment = $parser->parse();

        $expected = new ParsedFragment(
            null,
            [
                'test.css'
            ],
            [
                'test.js',
                'test_<?= $some[\'expression\'] ?>'
            ],
            [],
            ['', '']
        );

        $this->assertEquals($expected, $fragment);
    }

    public function testCanParseViewWithExtends(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_with_extends.php');

        $parser = new Parser($file);
        $fragment = $parser->parse();

        $expected = new ParsedFragment(
            'parent',
            [],
            [],
            [
                'section1' => '<div>Test HTML with @extends</div>' . "\n"
            ],
            ['', '']
        );

        $this->assertEquals($expected, $fragment);
    }

    public function testCanParseComplexView(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_complex.php');

        $parser = new Parser($file);
        $fragment = $parser->parse();

        $expected = new ParsedFragment(
            'parent',
            [
                'test1.css'
            ],
            [
                'test1.js',
                'test2_<?= $some[\'expression\'] ?>'
            ],
            [
                'section1' => '<div>Test HTML with @extends - section 1</div>' . "\n",
                'section2' => '<div>Test HTML with @extends - section 2</div>' . "\n"
            ],
            [
                '<?php phpinfo() ?>' . "\n",
                '<?php $a = \'test_string\' ?>' . "\n" . 'EXTRA' . "\n",
            ]
        );

        $this->assertEquals($expected, $fragment);
    }

    public function testFailsIfMultipleExtendsGiven(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_multiple_extends.php');

        $parser = new Parser($file);

        $this->expectExceptionMessage('Error in file ' . $file . ' in line 3 - There is already an \'@extends\' declared.');

        $parser->parse();
    }

    public function testFailsIfSectionWithoutExtendsGiven(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_section_without_extends.php');

        $parser = new Parser($file);

        $this->expectExceptionMessage('Error in file ' . $file . ' in line 1 - \'@section\' has no meaning if view extends nothing.');

        $parser->parse();
    }

    public function testFailsIfOpeningSectionBeforePreviousClosed(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_multiple_sections_open.php');

        $parser = new Parser($file);

        $this->expectExceptionMessage('Parse error in file ' . $file . ' in line 4 - A \'@section\' is already open (no \'@endsection\' found).');

        $parser->parse();
    }

    public function testFailsIfClosingSectionWhenNoSectionIsOpen(): void
    {
        $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_section_not_open.php');

        $parser = new Parser($file);

        $this->expectExceptionMessage('Parse error in file ' . $file . ' in line 4 - Cannot end section until no \'@section\' is open.');

        $parser->parse();
    }
}