<?php

namespace SwfTools\Tests\Processor;

use SwfTools\Binary\DriverContainer;
use SwfTools\Exception\InvalidArgumentException;
use SwfTools\Exception\RuntimeException;
use SwfTools\Processor\FlashFile;
use SwfTools\Tests\TestCase;

class FlashFileTest extends TestCase
{
    /**
     * @var FlashFile
     */
    protected $object;
    protected $destination;

    protected function setUp(): void
    {
        $this->destination = __DIR__ . '/../../../files/tmp.jpg';
        $this->object = new FlashFile(DriverContainer::create());
    }

    protected function tearDown(): void
    {
        if (file_exists($this->destination)) {
            unlink($this->destination);
        }
    }

    public function testRender()
    {
        $this->destination = $this->object->render(__DIR__ . '/../../../files/flashfile.swf', $this->destination);
        $this->assertTrue(file_exists($this->destination));

        unlink($this->destination);
    }

    /**
     * @expectedException SwfTools\Exception\RuntimeException
     * @expectedExceptionMessage Unable to load swfrender
     */
    public function testRenderNoBinary()
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Unable to load swfrender');
        $object = new FlashFile(DriverContainer::create(array('swfrender.binaries' => '/path/to/nowhere')));
        $object->render(__DIR__ . '/../../../files/flashfile.swf', '/target');
    }

    /**
     * @expectedException SwfTools\Exception\RuntimeException
     * @expectedExceptionMessage Unable to load swfextract
     */
    public function testExtractEmbeddedNoBinary()
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Unable to load swfextract');
        $object = new FlashFile(DriverContainer::create(array('swfextract.binaries' => '/path/to/nowhere')));
        $object->extractEmbedded(1, __DIR__ . '/../../../files/flashfile.swf', '/target');
    }

    /**
     * @expectedException SwfTools\Exception\RuntimeException
     * @expectedExceptionMessage Unable to load swfextract
     */
    public function testListEmbeddedNoBinary()
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Unable to load swfextract');
        $object = new FlashFile(DriverContainer::create(array('swfextract.binaries' => '/path/to/nowhere')));
        $object->listEmbeddedObjects(__DIR__ . '/../../../files/flashfile.swf');
    }

    /**
     * @expectedException SwfTools\Exception\RuntimeException
     * @expectedExceptionMessage Unable to load swfextract
     */
    public function testExtractFirstImageNoBinary()
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Unable to load swfextract');
        $object = new FlashFile(DriverContainer::create(array('swfextract.binaries' => '/path/to/nowhere')));
        $object->extractFirstImage(__DIR__ . '/../../../files/flashfile.swf', '/target');
    }

    /**
     * @expectedException \SwfTools\Exception\InvalidArgumentException
     */
    public function testRenderWrongDestination()
    {
        $this->expectException(InvalidArgumentException::class);
        $this->object->render(__DIR__ . '/../../../files/flashfile.swf', '');
    }

    /**
     * @doesNotPerformAssertions
     */
    public function testListEmbeddedObjects()
    {
        $this->object->listEmbeddedObjects(__DIR__ . '/../../../files/flashfile.swf');
    }

    public function testExtractEmbedded()
    {
        $this->object->extractEmbedded(1, __DIR__ . '/../../../files/flashfile.swf', $this->destination);
        $this->assertTrue(file_exists($this->destination));

        unlink($this->destination);
    }

    /**
     * @expectedException  \SwfTools\Exception\RuntimeException
     */
    public function testNoFirstImage()
    {
        $object = $this->getMockBuilder(FlashFile::class)
            ->onlyMethods(['listEmbeddedObjects'])
            ->disableOriginalConstructor()
            ->getMock();

        $object->expects($this->any())
            ->method('listEmbeddedObjects')
            ->willReturn([]);

        $this->expectException(RuntimeException::class);

        $object->extractFirstImage(__DIR__ . '/../../../files/flashfile.swf', $this->destination);
    }

    /**
     * @expectedException  \SwfTools\Exception\RuntimeException
     */
    public function testEmbeddedFailed()
    {
        $object = $this->getMockBuilder(FlashFile::class)
            ->onlyMethods(['listEmbeddedObjects'])
            ->disableOriginalConstructor()
            ->getMock();

        $object->expects($this->any())
            ->method('listEmbeddedObjects')
            ->willReturn(null);

        $this->expectException(RuntimeException::class);

        $object->extractFirstImage(__DIR__ . '/../../../files/flashfile.swf', $this->destination);
    }

    public function testExtractFirstImage()
    {
        $this->object->extractFirstImage(__DIR__ . '/../../../files/flashfile.swf', $this->destination);
        $this->assertTrue(file_exists($this->destination));

        unlink($this->destination);
    }

    /**
     * @expectedException \SwfTools\Exception\InvalidArgumentException
     */
    public function testExtractFirstImageFailWithoutDestination()
    {
        $this->expectException(InvalidArgumentException::class);
        $this->object->extractFirstImage(__DIR__ . '/../../../files/flashfile.swf', '');
    }

    /**
     * @expectedException  \SwfTools\Exception\RuntimeException
     */
    public function testExtractEmbeddedWrongId()
    {
        $this->expectException(RuntimeException::class);
        $this->object->extractEmbedded(-4, __DIR__ . '/../../../files/flashfile.swf', $this->destination);
    }

    /**
     * @expectedException  \SwfTools\Exception\RuntimeException
     */
    public function testExtractEmbeddedWrongOutput()
    {
        $this->expectException(RuntimeException::class);
        $this->object->extractEmbedded(1, __DIR__ . '/../../../files/flashfile.swf', '/dsmsdf/dslgfsdm');
    }
}
