<?php declare(strict_types=1);
namespace Newland\NeosViewHelpers\ViewHelpers\Media;

/*
 * This file is part of the "neos-viewhelpers" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Neos\FluidAdaptor\Core\ViewHelper\AbstractViewHelper;
use Neos\Media\Domain\Model\Image;
use Neos\Utility\Files;
use function Safe\mime_content_type;
use function Safe\stream_get_contents;

/**
 * Inline view helper.
 *
 * Outputs an inline-version of the given media node.
 */
class InlineViewHelper extends AbstractViewHelper
{

    /**
     * Main method.
     *
     * @param Image  $image  An image resource.
     * @param string $path   A path to an image resource.
     * @param string $class  Additional class for the SVG tag if it is an SVG.
     * @return string
     */
    public function render(Image $image = null, $path = null, $class = null): string
    {
        $contents = null;
        $mimeType = null;

        if ($image) {
            $contents = $this->getFileContentsFromObject($image);
            $mimeType = $image->getMediaType();
        } elseif ($path) {
            $contents = $this->getFileContentsFromPath($path);
            if ($contents) {
                $mimeType = mime_content_type(FLOW_PATH_ROOT . $path);
            }
        }

        if ($contents === null || $mimeType === null) {
            return '';
        }

        if ($mimeType === 'image/svg+xml') {
            return $this->prepareSvg($contents, $class);
        }

        return $this->prepareBlob($mimeType, $contents);
    }

    protected function prepareBlob(string $mimeType, string $contents): string
    {
        return 'data:' . $mimeType . ';base64, ' . base64_encode($contents);
    }

    protected function prepareSvg(string $contents, string $class = null): string
    {
        if ($class) {
            return $this->addClassToSvgContents($contents, $class);
        }

        return $contents;
    }

    protected function getFileContentsFromObject(Image $image): ?string
    {
        $stream = $image->getResource()->getStream();

        if (is_resource($stream)) {
            $contents = stream_get_contents($stream);
            fclose($stream);
            return (string) $contents;
        }

        return null;
    }

    private function getFileContentsFromPath($path): ?string
    {
        if (file_exists(FLOW_PATH_ROOT . $path)) {
            return Files::getFileContents(FLOW_PATH_ROOT . $path);
        }
        return null;
    }

    private function addClassToSvgContents(string $contents, string $class): string
    {
        return str_replace(
            '<svg',
            '<svg class="' . $class . '" ',
            $contents
        );
    }
}
