<?php

namespace AutoAdmin\Bundle\Media\Service;

use AutoAdmin\Bundle\Media\Mapper\MapperManager;
use AutoAdmin\Bundle\Media\Model\FileInterface;
use AutoAdmin\Bundle\Media\Model\ImageInterface;
use InvalidArgumentException;
use Liip\ImagineBundle\Service\FilterService;

class PublicPathGenerator
{
    const RESIZE_MODE_OUTBOUND = 'outbound';
    const RESIZE_MODE_INSET = 'inset';

    private MapperManager $mapperManager;
    private FilterService $imagine;

    public function __construct(MapperManager $mapper, FilterService $imagine)
    {
        $this->mapperManager = $mapper;
        $this->imagine = $imagine;
    }

    public function getResizedMediaPictureUrl(
        ImageInterface $media,
        int            $width,
        int            $height,
        string         $filter = 'default',
        array          $options = []
    ): string
    {
        if ($width <= 0 && $height <= 0) {
            throw new InvalidArgumentException("Invalid arguments, width & height must be greater than 0");
        }

        if ($width <= 0 || $height <= 0) {
            $dataSize = $this->recomputeImageSize($media, $width, $height);
            $width = $dataSize['width'];
            $height = $dataSize['height'];
        }

        $path = ltrim($this->getMediaUrl($media), '/');
        $options = $this->buildRuntimeOptions($width, $height, $options);

        return $this->imagine->getUrlOfFilteredImageWithRuntimeFilters($path, $filter, $options);
    }

    private function recomputeImageSize(ImageInterface $media, int $width, int $height): array
    {
        $ratio = $media->getWidth() / $media->getHeight();

        if ($width <= 0) {
            $width = $height * $ratio;
        }

        if ($height <= 0) {
            $height = (int)$width / $ratio;
        }

        return [
            'width' => $width,
            'height' => $height,
        ];
    }

    public function getMediaUrl(?FileInterface $media): ?string
    {
        if (empty($media) || empty($media->getFileName())) {
            return null;
        }

        $mapper = $this->mapperManager->getMapper($media);

        return $mapper->getPublicPath($media) . '/' . $media->getFileName();
    }

    private function buildRuntimeOptions(int $width, int $height, array $options = []): array
    {
        $sizeOptions = [
            'thumbnail' => ['size' => [$width, $height],],
        ];

        return array_merge_recursive($options, $sizeOptions);
    }
}
