<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components;


use CpCreation\VitiCore\Bridge\Symfony\Bundle\Glide\GenerateUri;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
use Symfony\UX\TwigComponent\Attribute\PostMount;
use Symfony\UX\TwigComponent\Attribute\PreMount;

#[AsTwigComponent(template: '@components/Image.html.twig')]
class Image
{
    public string $mapping = 'image';
    public bool $local = false; // True, permet de forcer l'affichage direct sans passer par glide
    public ?string $pathLandscape = null;
    public ?string $pathPortrait = null;
    public ?string $path = null;
    public float|string|null $ratio = null;
    public float|string|null $ratioLandscape = null;
    public float|string|null $ratioPortrait = null;
    public ?string $legend = null;
    public ?string $alt = null;
    public int $quality = GenerateUri::QUALITY;
    public string $fm = GenerateUri::FM;
    public string $fit = GenerateUri::FIT;
    public ?string $crop = null;
    public ?string $cropLandscape = null;
    public ?string $cropPortrait = null;
    public string $bgAlpha = '00000000';
    public bool $responsive = true;
    public bool $lazy = true;
    public float|int|null $imageWidth = null;
    public float|int|null $imageHeight = null;
    public string $fitLandscape = 'crop';
    public string $fitPortrait = 'crop';

    /**
     * @param array<string, mixed> $data
     *
     * @return array<string, mixed>
     */
    #[PreMount(priority: 10)]
    public function preMount(array $data): array
    {
        $resolver = new OptionsResolver();
        $resolver->setIgnoreUndefined(true);
        $resolver->setDefaults([
            'mapping' => $this->mapping,
            'local' => $this->local,
            'path' => $this->path,
            'pathLandscape' => $this->pathLandscape,
            'pathPortrait' => $this->pathPortrait,
            'ratio' => $this->ratio,
            'ratioLandscape' => $this->ratioLandscape,
            'ratioPortrait' => $this->ratioPortrait,
            'legend' => $this->legend,
            'alt' => $this->alt,
            'quality' => $this->quality,
            'fm' => $this->fm,
            'fit' => $this->fit,
            'crop' => $this->crop,
            'cropLandscape' => $this->cropLandscape,
            'cropPortrait' => $this->cropPortrait,
            'bgAlpha' => $this->bgAlpha,
            'responsive' => $this->responsive,
            'lazy' => $this->lazy,
            'imageWidth' => $this->imageWidth,
            'imageHeight' => $this->imageHeight,
            'fitLandscape' => $this->fitLandscape,
            'fitPortrait' => $this->fitPortrait,
        ]);
        $resolver->setAllowedTypes('mapping', ['string']);
        $resolver->setAllowedTypes('local', 'bool');
        $resolver->setAllowedValues('mapping', ['image', 'public']);
        $resolver->setAllowedTypes('pathLandscape', ['string', 'null']);
        $resolver->setAllowedTypes('pathPortrait', ['string', 'null']);
        $resolver->setAllowedTypes('legend', ['string', 'null']);
        $resolver->setAllowedTypes('alt', ['string', 'null']);
        $resolver->setAllowedValues('fm', ['jpg', 'pjpg', 'jpeg', 'png', 'gif', 'webp', 'avif']);
        $resolver->setAllowedValues('fit', ['cover', 'contain', 'max', 'fill',
            'fill-max', 'stretch', 'crop', 'crop-top-left', 'crop-top', 'crop-top-right',
            'crop-left', 'crop-center', 'crop-right', 'crop-bottom-left', 'crop-bottom', 'crop-bottom-right',
        ]);
        $resolver->setAllowedTypes('quality', 'int');
        $resolver->setAllowedTypes('responsive', 'bool');
        $resolver->setAllowedTypes('lazy', 'bool');
        $resolver->setAllowedTypes('ratio', ['string', 'null']);
        $resolver->setAllowedValues('ratio', ['2/3', '1/1', '3/4', '4/5', '4/3', '3/2', '16/9', '21/9', '3/1', '4/1', null]);
        $resolver->setAllowedTypes('ratioLandscape', ['string', 'null']);
        $resolver->setAllowedValues('ratioLandscape', ['2/3', '1/1', '3/4', '4/5', '4/3', '3/2', '16/9', '21/9', '3/1', '4/1', null]);
        $resolver->setAllowedTypes('ratioPortrait', ['string', 'null']);
        $resolver->setAllowedValues('ratioPortrait', ['2/3', '1/1', '3/4', '4/5', '4/3', '3/2', '16/9', '21/9', '3/1', '4/1', null]);

        $resolver->setAllowedValues('crop', fn ($value) => null === $value || (\is_string($value) && preg_match('/^\d+,\d+,\d+,\d+$/', $value)));
        $resolver->setAllowedValues('cropLandscape', fn ($value) => null === $value || (\is_string($value) && preg_match('/^\d+,\d+,\d+,\d+$/', $value)));
        $resolver->setAllowedValues('cropPortrait', fn ($value) => null === $value || (\is_string($value) && preg_match('/^\d+,\d+,\d+,\d+$/', $value)));
        $resolver->setAllowedValues('bgAlpha', fn ($value) => null === $value || (\is_string($value) && preg_match('/^[0-9A-Fa-f]{8}$/', $value)));

        if (isset($data['ratio'])) {
            $data['ratioLandscape'] = $data['ratio'];
            $data['ratioPortrait'] = $data['ratio'];
        }

        if (isset($data['crop'])) {
            $data['cropLandscape'] ??= $data['crop'];
            $data['cropPortrait'] ??= $data['crop'];
        }

        if (isset($data['responsive']) && !$data['responsive'] && !isset($data['ratioLandscape'])) {
            $resolver->setRequired('path');
            $resolver->setAllowedTypes('path', 'string');
            $resolver->setRequired('imageWidth');
            $resolver->setRequired('imageHeight');
            $resolver->setAllowedTypes('imageWidth', ['float', 'int', 'string']);
            $resolver->setAllowedTypes('imageHeight', ['float', 'int', 'string']);
        } else {
            $resolver->setRequired('pathLandscape');
        }

        if (!isset($data['ratioLandscape']) || !isset($data['ratioPortrait'])) {
            $resolver->setRequired('imageWidth');
            $resolver->setRequired('imageHeight');
            $resolver->setAllowedTypes('imageWidth', ['float', 'int', 'string']);
            $resolver->setAllowedTypes('imageHeight', ['float', 'int', 'string']);
        }

        return $resolver->resolve($data) + $data;
    }

    #[PostMount]
    public function postMount(): void
    {
        if (\is_string($this->ratio)) {
            [$a, $b] = explode('/', $this->ratio);
            $this->ratio = (float) $a / (float) $b;
            $this->ratioLandscape = $this->ratioPortrait = $this->ratio;
        }

        if (\is_string($this->ratioLandscape)) {
            [$a, $b] = explode('/', $this->ratioLandscape);
            $this->ratioLandscape = (float) $a / (float) $b;
            if (!$this->pathLandscape) {
                $this->pathLandscape = $this->path;
            }
        }

        if (\is_string($this->ratioPortrait)) {
            [$a, $b] = explode('/', $this->ratioPortrait);
            $this->ratioPortrait = (float) $a / (float) $b;
            if (!$this->pathPortrait) {
                $this->pathPortrait = $this->pathLandscape;
            }
        }

        $this->fitLandscape = $this->fit;
        $this->fitPortrait = $this->fit;

        if ($this->cropLandscape) {
            $this->fitLandscape = 'crop';
        }

        if ($this->cropPortrait) {
            $this->fitPortrait = 'crop';
        }

        if (!$this->ratioLandscape && $this->imageWidth && $this->imageHeight) {
            $this->fitLandscape = 'contain';
            $this->ratioLandscape = $this->imageWidth / $this->imageHeight;
        }

        if (!$this->ratioPortrait && $this->imageWidth && $this->imageHeight) {
            $this->fitPortrait = 'contain';
            $this->ratioPortrait = $this->imageWidth / $this->imageHeight;
        }
    }

    /**
     * @return array<int, array{width: float, height: float}>
     */
    public function generateSizes(float $ratio): array
    {
        $widths = [360, 540, 720, 900, 1080, 1296, 1512, 1728, 1950, 2100, 2260, 2450, 2700];
        $sizes = [];

        foreach ($widths as $width) {
            $height = $width / $ratio;
            $sizes[] = ['width' => $width, 'height' => round($height, 2)];
        }

        return $sizes;
    }
}
