<?php

namespace App\Helpers;

use Exception;

class ImageHandler
{
    private $image;
    private $imageType;
    private $quality = 75;

    public function __construct($imagePath)
    {
        $this->loadImage($imagePath);
    }

    private function loadImage($imagePath) {
        $imageInfo = getimagesize($imagePath);
        switch($imageInfo['mime']) {
            case 'image/jpeg':
                $this->image = imagecreatefromjpeg($imagePath);
                break;
            case 'image/png':
                $this->image = imagecreatefrompng($imagePath);
                break;
            case 'image/gif':
                $this->image = imagecreatefromgif($imagePath);
                break;
            default:
                // Check if Imagick extension is available for WebP conversion
                if (extension_loaded('imagick') && class_exists('Imagick')) {
                    $this->loadImageWithImagick($imagePath);
                } else {
                    throw new Exception('Unsupported image type');
                }
        }
    }

    private function loadImageWithImagick($imagePath) {
        $imagick = new Imagick($imagePath);
        $this->image = $imagick;
    }

    private function checkImageLoaded() {
        if (empty($this->image)) {
            throw new Exception('No image loaded. Use loadImage() first.');
        }
    }

    public function convertToWebP($outputFile, $quality = 75) {
        if ($this->image instanceof Imagick) {
            // Set WebP format and quality
            $this->image->setImageFormat('webp');
            $this->image->setImageCompressionQuality($quality);
            $this->image->writeImage($outputFile);
        } else {
            throw new Exception('WebP conversion requires Imagick extension');
        }
    }

    public function compress($quality, $outputFile) {
        $this->checkImageLoaded();  // Ensure image is loaded

        if ($this->image instanceof Imagick) {
            $this->image->setImageCompressionQuality($quality);
            $this->image->writeImage($outputFile);
        } else {
            $imageInfo = getimagesize($this->image);
            switch($imageInfo['mime']) {
                case 'image/jpeg':
                    imagejpeg($this->image, $outputFile, $quality);
                    break;
                case 'image/png':
                    imagepng($this->image, $outputFile, 9 - ($quality / 10));
                    break;
                case 'image/gif':
                    imagegif($this->image, $outputFile);
                    break;
                default:
                    throw new Exception('Unsupported image type');
            }
        }
    }

    public function convert($newFormat, $outputFile) {
        $this->checkImageLoaded();  // Ensure image is loaded

        if ($this->image instanceof Imagick) {
            $this->image->setImageFormat($newFormat);
            $this->image->writeImage($outputFile);
        } else {
            switch(strtolower($newFormat)) {
                case 'jpeg':
                case 'jpg':
                    imagejpeg($this->image, $outputFile);
                    break;
                case 'png':
                    imagepng($this->image, $outputFile);
                    break;
                case 'gif':
                    imagegif($this->image, $outputFile);
                    break;
                default:
                    throw new Exception('Unsupported image format');
            }
        }
    }

    public function crop($cropWidth, $cropHeight, $cropType = 'center') {
        $width = imagesx($this->image);
        $height = imagesy($this->image);
    
        switch($cropType) {
            case 'center':
                $x = ($width / 2) - ($cropWidth / 2);
                $y = ($height / 2) - ($cropHeight / 2);
                break;
            // Add more cases as needed
            default:
                throw new Exception('Unsupported crop type');
        }
    
        $this->image = imagecrop($this->image, ['x' => $x, 'y' => $y, 'width' => $cropWidth, 'height' => $cropHeight]);
    }

    public function save($filename, $imageType = IMAGETYPE_JPEG, $compression = 75, $permissions = null)
    {
        if ($imageType == IMAGETYPE_JPEG) {
            imagejpeg($this->image, $filename, $compression);
        } elseif ($imageType == IMAGETYPE_GIF) {
            imagegif($this->image, $filename);
        } elseif ($imageType == IMAGETYPE_PNG) {
            imagepng($this->image, $filename);
        }

        if ($permissions != null) {
            chmod($filename, $permissions);
        }
    }

    public function output($imageType = IMAGETYPE_JPEG)
    {
        if ($imageType == IMAGETYPE_JPEG) {
            imagejpeg($this->image);
        } elseif ($imageType == IMAGETYPE_GIF) {
            imagegif($this->image);
        } elseif ($imageType == IMAGETYPE_PNG) {
            imagepng($this->image);
        }
    }

    public function getWidth()
    {
        return imagesx($this->image);
    }

    public function getHeight()
    {
        return imagesy($this->image);
    }

    public function resizeToHeight($height)
    {
        $ratio = $height / $this->getHeight();
        $width = $this->getWidth() * $ratio;
        $this->resize($width, $height);
    }

    public function resizeToWidth($width)
    {
        $ratio = $width / $this->getWidth();
        $height = $this->getheight() * $ratio;
        $this->resize($width, $height);
    }

    public function scale($scale)
    {
        $width = $this->getWidth() * $scale / 100;
        $height = $this->getheight() * $scale / 100;
        $this->resize($width, $height);
    }

    public function resize($width, $height)
    {
        $new_image = imagecreatetruecolor($width, $height);
        imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
        $this->image = $new_image;
    }
}
