<?php

defined('_JEXEC') or die;

/* Lazy Slider for Joomla!
--------------------------------------------------------------
 Copyright (C) 2017 AddonDev. All rights reserved.
 Website: https://addondev.com
 GitHub: https://github.com/philip-sorokin
 Developer: Philip Sorokin
 Location: Russia, Moscow
 E-mail: philip.sorokin@gmail.com
 Created: October 2017
 License: GNU GPLv2 http://www.gnu.org/licenses/gpl-2.0.html
--------------------------------------------------------------- */

class modLazysliderHelper
{
	public static $started = false;
	
	protected static $cachepath;
	protected static $cachedImage;
	protected static $sourceImage;
	protected static $sourceInfo;
	protected static $src;
	protected static $width;
	protected static $height;
	protected static $quality;
	protected static $maxAge;
	
	public static function getAjax()
	{
		if (ob_get_level())
		{
			ob_end_clean();
		}
		
		$app = JFactory::getApplication();
		
		self::$cachepath = JPATH_CACHE . '/mod_lazyslider';
		self::$src = urldecode($app->input->getStr('s'));
		self::$width = $app->input->getUInt('w');
		self::$height = $app->input->getUInt('h');
		self::$quality = $app->input->getUInt('q');
		self::$maxAge = $app->input->getUInt('a', 43800);
		
		if (!self::$quality || self::$quality > 100)
		{
			self::$quality = 75;
		}
		
		if (strpos(self::$src, './') !== false || strpos(self::$src, '.\\') !== false)
		{
			self::setResponseAndExit(403, 'Using relative paths is forbidden!');
		}
		
		$dotpos = mb_strrpos(self::$src, '.');
		
		if ($dotpos === false)
		{
			self::setResponseAndExit(400, 'Unrecognized file extension.');
		}
		
		$extension = mb_substr(self::$src, $dotpos + 1);
		$validExtensions = ['jpg', 'jpeg', 'png', 'gif'];
		$extensionKey = array_search($extension, $validExtensions);
		
		if ($extensionKey === false)
		{
			self::setResponseAndExit(400, 'Invalid file extension. Allowed extensions: ' . implode(', ', $validExtensions));
		}
		
		$hash = md5(implode(':', [self::$src, self::$width, self::$height, self::$quality]));
		
		self::$sourceImage = JPATH_ROOT . self::$src;
		self::$cachedImage = self::$cachepath . '/' . $hash . '.' . $validExtensions[$extensionKey];
		self::$sourceInfo = @getimagesize(self::$sourceImage);
		
		if (!self::$sourceInfo)
		{
			self::setResponseAndExit(404, 'Source image was not found.');
		}
		
		if (!file_exists(self::$cachedImage))
		{
			self::create();
		}
		else if (filemtime(self::$sourceImage) > filemtime(self::$cachedImage))
		{
			unlink(self::$cachedImage);
			self::create();
		}
		
		$size = @filesize(self::$cachedImage);
		
		if (!$size)
		{
			self::setResponseAndExit(500, 'Error: unable to create a file. Check permissions of the cache folder.');
		}
		
		header("Content-type: " . self::$sourceInfo['mime']);
		header("Cache-Control: max-age=" . (self::$maxAge * 60));
		header("Content-Length: " . $size);
		
		readfile(self::$cachedImage);
		
		exit;
	}
	
	protected static function create()
	{
		$original_width = self::$sourceInfo[0];
		$original_height = self::$sourceInfo[1];
		
		switch(strtolower(substr(self::$sourceInfo['mime'], 6)))
		{
			case 'jpg'  :
			case 'jpeg' : $type = 'jpeg';
				break;
			case 'png'  : $type = 'png';
				break;
			case 'gif'  : $type = 'gif';
				break;
			default : self::setResponseAndExit(400, 'Mime type of the source image is invalid.');
		}
		
		if (self::$width > $original_width)
		{
			self::$width = $original_width;
		}
		
		if (self::$height > $original_height)
		{
			self::$height = $original_height;
		}
		
		if (!function_exists('imagecreatetruecolor'))
		{
			self::setResponseAndExit(500, 'Error: GD Library is not installed on your server. Please, contact your hosting provider.');
		}
		
		$canvas = imagecreatetruecolor(self::$width, self::$height);
		$image = call_user_func("imagecreatefrom{$type}", self::$sourceImage);
		
		imagecopyresampled($canvas, $image, 0, 0, 0, 0, self::$width, self::$height, $original_width, $original_height);
		
		if (!is_dir(self::$cachepath))
		{
			mkdir(self::$cachepath);
		}
		
		if ($type === 'png')
		{
			self::$quality = 9 - round(90 * self::$quality / 1000);
		}
		
		call_user_func("image{$type}", $canvas, self::$cachedImage, self::$quality);
		imagedestroy($canvas);
	}
	
	protected static function setResponseAndExit($code, $status = '')
	{
		header("Status: $code $status");
		http_response_code($code);
		
		exit($status);
	}
}
