<?php

declare(strict_types=1);

namespace Drupal\KernelTests\Core\Image;

use Drupal\system\Plugin\ImageToolkit\GDToolkit;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * GD image toolkit image manipulation of GIF images.
 */
#[CoversClass(GDToolkit::class)]
#[Group('Image')]
#[RequiresPhpExtension('gd')]
#[RunTestsInSeparateProcesses]
class GdToolkitGifImageManipulationTest extends GdToolkitImageManipulationTestBase {

  /**
   * {@inheritdoc}
   */
  protected string $sourceTestImage = 'image-test.gif';

  /**
   * {@inheritdoc}
   */
  public static function providerOperationTestCases(): array {
    $ret = parent::providerOperationTestCases();

    if (PHP_VERSION_ID >= 80500 && array_key_exists('rotate_transparent_5', $ret)) {
      $ret['rotate_transparent_5'][3]['corners'][0] = [255, 93, 0, 46];
    }

    return $ret;
  }

  /**
   * Tests for GIF images with transparency.
   */
  public function testGifTransparentImages(): void {
    // Test loading an indexed GIF image with transparent color set.
    // Color at top-right pixel should be fully transparent.
    $file = 'image-test-transparent-indexed.gif';
    $image = $this->imageFactory->get('core/tests/fixtures/files/' . $file);
    $gd_image = $image->getToolkit()->getImage();
    $color_index = imagecolorat($gd_image, $image->getWidth() - 1, 0);
    $color = array_values(imagecolorsforindex($gd_image, $color_index));
    $this->assertEquals(static::ROTATE_TRANSPARENT, $color, "Image {$file} after load has full transparent color at corner 1.");

    // Test deliberately creating a GIF image with no transparent color set.
    // Color at top-right pixel should be fully transparent while in memory,
    // fully opaque after flushing image to file.
    $file = 'image-test-no-transparent-color-set.gif';
    $file_path = $this->directory . '/' . $file;
    // Create image.
    $image = $this->imageFactory->get();
    $image->createNew(50, 20, 'gif', NULL);
    $gd_image = $image->getToolkit()->getImage();
    $color_index = imagecolorat($gd_image, $image->getWidth() - 1, 0);
    $color = array_values(imagecolorsforindex($gd_image, $color_index));
    $this->assertEquals(static::ROTATE_TRANSPARENT, $color, "New GIF image with no transparent color set after creation has full transparent color at corner 1.");
    // Save image.
    $this->assertTrue($image->save($file_path), "New GIF image {$file} was saved.");
    // Reload image.
    $image_reloaded = $this->imageFactory->get($file_path);
    $gd_image = $image_reloaded->getToolkit()->getImage();
    $color_index = imagecolorat($gd_image, $image_reloaded->getWidth() - 1, 0);
    $color = array_values(imagecolorsforindex($gd_image, $color_index));
    // Check explicitly for alpha == 0 as the rest of the color has been
    // compressed and may have slight difference from full white.
    $this->assertEquals(0, $color[3], "New GIF image {$file} after reload has no transparent color at corner 1.");

    // Test loading an image whose transparent color index is out of range.
    // This image was generated by taking an initial image with a palette size
    // of 6 colors, and setting the transparent color index to 6 (one higher
    // than the largest allowed index), as follows:
    // @code
    // $image = imagecreatefromgif('core/tests/fixtures/files/image-test.gif');
    // imagecolortransparent($image, 6);
    // imagegif($image, 'core/tests/fixtures/files/image-test-transparent-out-of-range.gif');
    // @endcode
    // This allows us to test that an image with an out-of-range color index
    // can be loaded correctly.
    $file = 'image-test-transparent-out-of-range.gif';
    $image = $this->imageFactory->get('core/tests/fixtures/files/' . $file);
    $this->assertTrue($image->isValid(), "Image '$file' after load should be valid, but it is not.");
    $this->assertTrue(imageistruecolor($image->getToolkit()->getImage()), "Image '$file' after load should be a truecolor image, but it is not.");
  }

}
