<?php

namespace Hura8\System;

use Intervention\Image\ImageManager as InterventionImage;

// 12-Nov-2022
// class to manipulate images: create/resize/convert/water-mark ...
// reference guide:
// https://image.intervention.io/v2/api/make
//

final class HuraImage
{

    /* @var $objInterventionImage InterventionImage */
    private $objInterventionImage;


    public function __construct() {
        $this->objInterventionImage = new InterventionImage();
    }


    /**
     * optimize file size of an image and resize its width to the max_width it
     *
     * @param string $file_dir __DIR__."/media/product/'
     * @param string $file_name file.jpg
     * @param int $max_width
     * @return bool
     */
    public function optimizeFile(string $file_dir, string $file_name, int $max_width = 1200): bool
    {
        $file_path = $file_dir . DIRECTORY_SEPARATOR . $file_name;
        $random_str = IDGenerator::createStringId(10);
        $clone_file = $file_dir . DIRECTORY_SEPARATOR . $random_str. '-' . $file_name;

        if(!copy($file_path, $clone_file)) {
            return false;
        }

        $img = $this->objInterventionImage->make($clone_file);

        list ( $img_width ) = getimagesize($clone_file);
        if($img_width > $max_width) {
            $img->resize($max_width, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($file_path, 90);
        }else{
            $img->save($file_path, 90);
        }

        // then delete the clone
        unlink($clone_file);

        return file_exists($file_path);
    }


    /**
     * create image to local system
     * copy from https://image.intervention.io/v2/api/make
     * @param mixed $source
     * Source to create an image from. The method responds to the following input types:
        string - Path of the image in filesystem.
        string - URL of an image (allow_url_fopen must be enabled).
        string - Binary image data.
        string - Data-URL encoded image data.
        string - Base64 encoded image data.
        resource - PHP resource of type gd. (when using GD driver)
        object - Imagick instance (when using Imagick driver)
        object - Intervention\Image\Image instance
        object - SplFileInfo instance (To handle Laravel file uploads via Symfony\Component\HttpFoundation\File\UploadedFile)
     *
     * @param string $saved_file_path __DIR__."/media/product/file.jpg'
     * @return bool
     */
    public function create($source, $saved_file_path) {

        try {
            $this->objInterventionImage->make($source)->save($saved_file_path, 90);
        }catch (\Exception $e) {
            // NotReadableException: Unsupported image type. GD/PHP installation does not support WebP format
            @copy($source, $saved_file_path);
        }

        return file_exists($saved_file_path);
    }


    /**
     * https://image.intervention.io/v2/api/encode
     * @param $local_file_path
     * @param string $format jpg | png | gif | webp | data-url
     * @return bool
     */
    public function convertFileFormat($local_file_path, $format ) {

        // if same format as local file, stop
        $file_ext = strtolower(substr(strrchr($local_file_path, '.'), 1));
        if($file_ext == $format) {
            return true;
        }

        $saved_file_path = substr($local_file_path, 0,  strrpos($local_file_path,".") ) . ".". $format;

        $this->objInterventionImage->make($local_file_path)
            ->encode($format, 100)
            ->save($saved_file_path, 90);

        return file_exists($saved_file_path);
    }


    /**
     * guide: https://image.intervention.io/v2/api/resize
     * @param $local_file_path
     * @param array $size_key_dimension array('small' => ['width' => 100, 'height' => 100], 'large' => ['width' => 200, 'height' => 200] )
     * @param string $resized_file_directory
     * @return array
     */
    public function resize($local_file_path, array $size_key_dimension, $resized_file_directory = '') {

        $stored_directory = ($resized_file_directory) ?: substr($local_file_path, 0,  strrpos($local_file_path,"/") ) ;
        //echo "<p>stored_directory: ".$stored_directory;

        $file_name = substr(strrchr($local_file_path,"/"), 1);
        //echo "<p>file_name: ".$file_name;

        $expected_files = [];
        foreach ($size_key_dimension as $key => $dimension) {

            $resized_file_name = $key. IMAGE_FILE_SEPARATOR . $file_name;
            $expected_files[] = $resized_file_name;

            $saved_file_path = $stored_directory . "/".$resized_file_name;
            $new_width  = $dimension['width'] ?? null;
            $new_height = $dimension['height'] ?? null;

            $img = $this->objInterventionImage->make($local_file_path);

            if(!$new_width || !$new_height) {
                $img->resize($new_width, $new_height, function ($constraint) {
                    $constraint->aspectRatio();
                })->save($saved_file_path, 90);
            }else{
                $img->resize($new_width, $new_height)->save($saved_file_path, 90);
            }

            $img->destroy();
        }

        //echo "<p>Expected files: ".\json_encode($expected_files);
        $exist_all = true;
        foreach ($expected_files as $_file) {
            if(!file_exists($stored_directory . "/". $_file)) {
                $exist_all = false;
                break;
            }
        }

        return array($exist_all, $expected_files, $stored_directory);
    }


    /**
     * @param $original_file_path
     * @param $img_watermark_path
     * @param string $position
     */
    public function watermark($original_file_path, $img_watermark_path, $position='bottom-right') {
        $img = $this->objInterventionImage->make($original_file_path);
        $watermark = $this->objInterventionImage->make($img_watermark_path);
        $img->insert($watermark, $position, 10, 10);
        //$img->bac ($destinationPath.'/'.$fileName);
        $img->save($original_file_path, 100);
    }

}
