<?php

namespace Croogo\Core\View\Helper;

use Cake\Utility\Hash;
use Cake\View\Helper\HtmlHelper;

/**
 * @package Croogo.Croogo.View.Helper
 * @version 1.1
 * @author Josh Hundley
 * @author Jorge Orpinel <jop@levogiro.net> (changes)
 */
class ImageHelper extends HtmlHelper
{

    public $helpers = [
        'Html',
        'Theme',
        'Url',
    ];

    /**
     * Automatically resizes an image and returns formatted IMG tag
     *
     * Options:
     * - aspect Maintain aspect ratio. Default: true
     * - uploadsDir Upload directory name. Default: 'uploads'
     * - cachedir Cache directory name. Default: 'resized'
     * - resizeInd: String to check in filename indicating that it was resized
     *
     * @param string $path Path to the image file, relative to the webroot/img/ directory.
     * @param int $width of returned image
     * @param int $height of returned image
     * @param array $options Options
     * @param array $htmlAttributes Array of HTML attributes.
     * @param bool $return this method should return a value or output it. This overrides AUTO_OUTPUT.
     * @return mixed Either string or echoes the value, depends on AUTO_OUTPUT and $return.
     * @access public
     */
    public function resize($path, $width, $height, $options = [], $htmlAttributes = [], $return = false)
    {
        if (is_bool($options)) {
            $options = ['aspect' => $options];
        }
        $options = Hash::merge([
            'aspect' => true,
            'uploadsDir' => 'uploads',
            'cacheDir' => 'resized',
            'resizedInd' => '.resized-',
            'templates' => []
        ], $options);
        $aspect = $options['aspect'];
        $uploadsDir = $options['uploadsDir'];
        $cacheDir = $options['cacheDir'];
        $resizedInd = $options['resizedInd'];
        $imgClass = $this->Theme->getCssClass('thumbnailClass');

        if (empty($htmlAttributes['alt'])) {
            $htmlAttributes['alt'] = 'thumb';
        }

        if (!array_key_exists('class', $htmlAttributes)) {
            $htmlAttributes['class'] = $imgClass;
        }

        $sourcefile = WWW_ROOT . DS . $path;

        if (!file_exists($sourcefile)) {
            return;
        }

        $size = getimagesize($sourcefile);

        if ($aspect) {
            if (($size[1] / $height) > ($size[0] / $width)) {
                $width = ceil(($size[0] / $size[1]) * $height);
            } else {
                $height = ceil($width / ($size[0] / $size[1]));
            }
        }

        $dimension = $resizedInd . $width . 'x' . $height;
        $parts = pathinfo(WWW_ROOT . $path);
        if ($resizedInd === '') {
            // legacy format
            $filename = $parts['filename'];
            $filename = preg_replace('/^[0-9]*x[0-9]*_/', '', $filename);
            $resized = $width . 'x' . $height . '_' . $filename . '.' . $parts['extension'];
        } else {
            $filename = $parts['filename'];
            $filename = preg_replace('/' . preg_quote($resizedInd) . '[0-9]*x[0-9]*/', '', $filename);
            $resized = $filename . $dimension . '.' . $parts['extension'];
        }
        $relfile = '/';
        if ($uploadsDir) {
            $relfile .= ltrim($uploadsDir, '/') . '/';
        }
        if ($cacheDir) {
            $relfile .= ltrim($cacheDir, '/') . '/';
        }
        $relfile .= $resized;
        $cachefile = WWW_ROOT . ltrim($relfile, '/');

        $targetDir = dirname($cachefile);
        if (!is_dir($targetDir)) {
            mkdir($targetDir);
        }

        $cached = false;
        if (file_exists($cachefile)) {
            $csize = getimagesize($cachefile);

            // image is cached
            $cached = ($csize[0] == $width && $csize[1] == $height);

            // check if up to date
            if (filemtime($cachefile) < filemtime($sourcefile)) {
                $cached = false;
            }
        }

        if (!$cached) {
            $resize = ($size[0] > $width || $size[1] > $height) || ($size[0] < $width || $size[1] < $height);
        } else {
            $resize = false;
        }

        if ($resize) {
            $this->_resize($sourcefile, $size, $cachefile, $width, $height);
        } elseif (!file_exists($cachefile)) {
            copy($sourcefile, $cachefile);
        }

        $templater = $this->templater();
        $newTemplates = $options['templates'];

        if ($newTemplates) {
            $templater->push();
            $templateMethod = is_string($options['templates']) ? 'load' : 'add';
            $templater->{$templateMethod}($options['templates']);
        }
        unset($options['templates']);

        return $templater->format('image', [
            'url' => $this->Url->webroot($relfile),
            'attrs' => $templater->formatAttributes($htmlAttributes),
        ]);
    }

    /**
     * Convenience method to resize image
     *
     * @param string $source File name of the source image
     * @param array $sourceSize Result of getimagesize() against $source
     * @param string $target File name of the target image
     * @param int $w Target Image width
     * @param int $h Target image height
     * @return void
     */
    protected function _resize($source, $sourceSize, $target, $w, $h)
    {
        $types = [1 => "gif", "jpeg", "png", "swf", "psd", "wbmp"];
        $transparency = ["gif", "png"];

        $format = $types[$sourceSize[2]];
        $sw = $sourceSize[0];
        $sh = $sourceSize[1];

        $image = call_user_func('imagecreatefrom' . $format, $source);
        if (function_exists('imagecreatetruecolor')) {
            $temp = imagecreatetruecolor($w, $h);
            if (in_array($format, $transparency)) {
                $this->_setupTransparency($temp, $w, $h);
            }
            imagecopyresampled($temp, $image, 0, 0, 0, 0, $w, $h, $sw, $sh);
        } else {
            $temp = imagecreate($w, $h);
            if (in_array($format, $transparency)) {
                $this->_setupTransparency($temp, $w, $h);
            }
            imagecopyresized($temp, $image, 0, 0, 0, 0, $w, $h, $sw, $sh);
        }
        if (is_writable(dirname($target))) {
            call_user_func('image' . $format, $temp, $target);
            imagedestroy($image);
            imagedestroy($temp);
        }
    }

    /**
     * Convenience method to setup image transparency
     *
     * @param resource $image Image resource
     * @param int $w Width
     * @param int $h Height
     * @return void
     */
    protected function _setupTransparency($image, $w, $h)
    {
        imagealphablending($image, false);
        imagesavealpha($image, true);
        $transparent = imagecolorallocatealpha($image, 255, 255, 255, 127);
        imagefilledrectangle($image, 0, 0, $w, $h, $transparent);
    }
}
