<?php /** @noinspection PhpUnused */

class GdImageClass
{
    /**
     * @var string[]
     */
    public static $extensions = [
        'png', 'jpeg', 'jpg'
    ];

    /**
     * @param $suffix
     * @return bool
     */
    public static function isSupportSuffix($suffix): bool
    {
        return in_array($suffix, self::$extensions, true);
    }

    /**
     * @var \GdImage|false|resource
     */
    protected $image;

    /**
     * @param string $imagePath
     * @param string|null $extension
     * @throws \ExtendException
     * @throws \Exception
     */
    public function __construct(string $imagePath, string $extension = null)
    {
        $ext = $extension ?? strtolower(pathinfo($imagePath, PATHINFO_EXTENSION));
        if (empty($ext)) {
            throw new ExtendException('unrecognized image type');
        }
        $this->image = $this->createImageFromPath($imagePath, $ext);

        if ($this->image === false) {
            throw new ExtendException('Unsupported image type: ' . $ext);
        }
    }

    /**
     * @throws \Exception
     */
    function convertToValidPng($filePath, $outputPath)
    {
        // 获取文件内容
        $fileContent = file_get_contents($filePath);
        if ($fileContent === false) {
            throw new Exception('读取文件失败。');
        }

        // 从文件内容创建图像
        $image = imagecreatefromstring($fileContent);
        if ($image === false) {
            throw new Exception('该文件不是有效的图像。');
        }

        // 将图像保存为有效的 PNG 文件
        if (!imagepng($image, $outputPath)) {
            throw new Exception('保存图像为 PNG 文件失败。');
        }

        // 释放内存
        imagedestroy($image);
    }

    /**
     * @param $filePath
     * @param $outputPath
     * @return void
     * @throws \Exception
     */
    function convertToValidJpg($filePath, $outputPath)
    {
        // 获取文件内容
        $fileContent = file_get_contents($filePath);
        if ($fileContent === false) {
            throw new Exception('读取文件失败。');
        }

        // 从文件内容创建图像
        $image = imagecreatefromstring($fileContent);
        if ($image === false) {
            throw new Exception('该文件不是有效的图像。');
        }

        // 将图像保存为有效的 PNG 文件
        if (!imagejpeg($image, $outputPath)) {
            throw new Exception('保存图像为 PNG 文件失败。');
        }

        // 释放内存
        imagedestroy($image);
    }

    /**
     * @param $filePath
     * @return bool
     */
    function isValidPng($filePath): bool
    {
        $imageInfo = getimagesize($filePath);
        return $imageInfo && $imageInfo[2] === IMAGETYPE_PNG;
    }

    //判断是否为有效的jpg文件

    /**
     * @param $filePath
     * @return bool
     */
    function isValidJpg($filePath): bool
    {
        $imageInfo = getimagesize($filePath);
        return $imageInfo && $imageInfo[2] === IMAGETYPE_JPEG;
    }


    /**
     * @param string $imagePath
     * @param string $ext
     * @return \GdImage|false|resource
     * @throws \Exception
     */
    private function createImageFromPath(string $imagePath, string $ext)
    {
        switch ($ext) {
            case 'png':
                if (!$this->isValidPng($imagePath)){
                    $this->convertToValidPng($imagePath, $imagePath);
                }
                return imagecreatefrompng($imagePath);
            case 'gif':
                return imagecreatefromgif($imagePath);
            case 'jpeg':
            case 'jpg':
                if (!$this->isValidJpg($imagePath)){
                    $this->convertToValidJpg($imagePath, $imagePath);
                }
                return imagecreatefromjpeg($imagePath);
            case 'bmp':
                return imagecreatefrombmp($imagePath);
            case 'webp':
                return imagecreatefromwebp($imagePath);
            case 'xbm':
                return imagecreatefromxbm($imagePath);
            case 'xpm':
                return imagecreatefromxpm($imagePath);
            default:
                return false;
        }
    }

    /**
     * @return int
     * @noinspection PhpUnusedPrivateMethodInspection
     */
    private function getFileSize(): int
    {
        ob_start();
        imagejpeg($this->image);
        $content = ob_get_clean();
        /** @noinspection PhpComposerExtensionStubsInspection */
        return (int)bcdiv((string)strlen($content), "1024", 4);
    }

    /**
     * @param int $width
     * @param int $height
     * @return $this
     */
    public function resize(int $width, int $height): self
    {
        $newImage = imagecreatetruecolor($width, $height);
        imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $width, $height, imagesx($this->image), imagesy($this->image));
        imagedestroy($this->image);
        $this->image = $newImage;
        return $this;
    }

    /**
     * @param string $targetPath
     * @param string $format
     * @return string
     * @throws \ExtendException
     */
    public function convertTo(string $targetPath, string $format): string
    {
        if (!imageistruecolor($this->image)) {
            imagepalettetotruecolor($this->image);
        }
        switch (strtolower($format)) {
            case 'png':
                imagepng($this->image, $targetPath);
                break;
            case 'gif':
                imagegif($this->image, $targetPath);
                break;
            case 'jpeg':
            case 'jpg':
                imagejpeg($this->image, $targetPath);
                break;
            case 'bmp':
                imagebmp($this->image, $targetPath);
                break;
            case 'webp':
                imagewebp($this->image, $targetPath);
                break;
            default:
                throw new ExtendException('Unsupported target format: ' . $format);
        }

        imagedestroy($this->image);
        return $targetPath;
    }
}