<?php
/*
 *
 * @package		ARI Framework
 * @author		ARI Soft
 * @copyright	Copyright (c) 2011 www.ari-soft.com. All rights reserved
 * @license		GNU/GPL (http://www.gnu.org/copyleft/gpl.html)
 * 
 */   
(defined('_JEXEC') && defined('ARI_FRAMEWORK_LOADED')) or die;

AriKernel::import('Image.ImageHelper');
AriKernel::import('CSV.CSVParser');
AriKernel::import('SimpleTemplate.SimpleTemplate');
AriKernel::import('Utils.AppUtils');

jimport('joomla.filesystem.path');
jimport('joomla.filesystem.folder');

class AriThumbnail
{
	var $_prefix;
	var $_cacheDir;

	function __construct($prefix = 'arithumb', $cacheDir = null)
	{
		$this->_prefix = $prefix;
		$this->_cacheDir = $cacheDir;
	}
	
	function getStoredData($params)
	{
		$correctedParams = $this->getCorrectedParameters($params);
		$cachePeriod = $correctedParams['cachePeriod'];
		$data = null;

		if ($cachePeriod > 0)
		{
			$needReCache = true;
			$cacheDir = $this->_cacheDir;
			$key = $correctedParams['key'];
			$checkSum = $correctedParams['checkSum'];
			
			$cacheCheckFile = $cacheDir . DS . $key . '.txt';
			$cacheDataFile = $cacheDir . DS . $key . '.php';
			if (@file_exists($cacheCheckFile) && @file_exists($cacheDataFile))
			{
				$oldCheckSum = trim(@file_get_contents($cacheCheckFile));
				if ($oldCheckSum == $checkSum)
				{
					$needReCache = (filemtime($cacheCheckFile) + $cachePeriod * 60 < time());
				}
			}
			
			global $_THUMB_CACHED_DATA;
			if ($needReCache)
			{
				$this->prepare($correctedParams);
				$data = $this->getData($correctedParams);
				
				$h = fopen($cacheCheckFile, 'w');
				fwrite($h, $checkSum);
				fclose($h);
				
				if (!isset($_THUMB_CACHED_DATA)) $_THUMB_CACHED_DATA = array();
				
				$cachedData = var_export($data, true);
				$h = fopen($cacheDataFile, 'w');
				fwrite($h, sprintf('<?php%1$sdefined("ARI_FRAMEWORK_LOADED") or die("Direct Access to this location is not allowed.");%1$s$_THUMB_CACHED_DATA["%2$s"] = %3$s;?>',
					"\n",
					$key,
					$cachedData));
				fclose($h);
			}
			else 
			{
				require_once $cacheDataFile;

				$data = $_THUMB_CACHED_DATA[$key];
			}
		}
		else 
		{
			$this->prepare($correctedParams);
			$data = $this->getData($correctedParams);
		}

		if ($correctedParams['sortBy'] == 'random')
			shuffle($data);

		return $data;
	}
	
	function prepare($params)
	{		
		if ($params['generateThumbs'])
			$this->generateThumbnails($params);
	}

	function getData($params)
	{
		$data = array();
		
		$prefix = $this->_prefix;
		$descrFile = $params['descrFile'];
		$thumbPath = $params['thumbPath'];
		$cacheDir = $this->_cacheDir;
		$cacheUri = str_replace('\\', '/', $cacheDir);
		$rootUri = str_replace('\\', '/', JPATH_ROOT . DIRECTORY_SEPARATOR);
		if (strpos($cacheUri, $rootUri) === 0)
			$cacheUri = substr($cacheUri, strlen($rootUri));
        $rootUri = JURI::root(true) . '/';
        $cacheUri = $rootUri . str_replace(DS, '/', $cacheUri);

		$folders = $params['folders'];
		$thumbWidth = $params['thumbWidth'];
		$thumbHeight = $params['thumbHeight'];
		$sortBy = $params['sortBy'];
		$sortDir = $params['sortDir'];
		$thumbType = $params['thumbType'];
		$thumbTypeParams = $params['thumbTypeParams'];
		$thumbBehavior = $thumbType == 'resize' ? AriUtils::getParam($thumbTypeParams, 'behavior') : null;
		
		$navThumbPath = $params['navThumbPath'];
		$navThumbWidth = $params['navThumbWidth'];
		$navThumbHeight = $params['navThumbHeight'];
		//$emptyTitle = $params['emptyTitle'];
		//$needProcessEmptyTitle = ($emptyTitle && strpos($emptyTitle, '{$') !== false);

		foreach ($folders as $folder)
		{
			$descriptions = $this->getDescriptions($descrFile, $folder);
			$files = $this->getImageFiles($folder, $params['fileFilter']);
			$inCSV = false;
			$folderData = array();
			foreach ($files as $file)
			{
				$dataItem = null;
				$fileUri = $rootUri . str_replace(DS, '/', $file);
				$filePath = JPATH_ROOT . DS . $file;
				$imgSize = AriImageHelper::getImageDimension($filePath);

				$baseFileName = basename($file);
				$thumbImagePath = $thumbPath
					? JPATH_ROOT . DS . $folder . DS . str_replace('{$fileName}', $baseFileName, $thumbPath)
					: null;

				$navThumbImagePath = $navThumbPath
					? JPATH_ROOT . DS . $folder . DS . str_replace('{$fileName}', $baseFileName, $navThumbPath)
					: null;

				if ($thumbImagePath && file_exists($thumbImagePath) && is_readable($thumbImagePath))
				{
					$thumbSize = getimagesize($thumbImagePath);
					$dataItem = array(
						'image' => array(
							'url' => $fileUri,
							'w' => $imgSize['w'],
							'h' => $imgSize['h']
						),
						'thumb' => array(
							'url' => str_replace(DS, '/', $folder . DS . str_replace('{$fileName}', $baseFileName, $thumbPath)),
							'w' => $thumbSize[0],
							'h' => $thumbSize[1]
						)
					);
				}
				else
				{
					$thumbSize = AriImageHelper::getThumbnailDimension($filePath, $thumbWidth, $thumbHeight, $thumbBehavior);
					$dataItem = array(
						'image' => array(
							'url' => $fileUri,
							'w' => $imgSize['w'],
							'h' => $imgSize['h']
						),
						'thumb' => array(
							'url' => $fileUri,
							'w' => $thumbSize['w'],
							'h' => $thumbSize['h']
						)
					);
					
					if ($thumbSize['w'] && $thumbSize['h'])
					{
						$thumbFile = AriImageHelper::generateThumbnailFileName($prefix, $filePath, $thumbSize['w'], $thumbSize['h'], $thumbType);
						if (@file_exists($cacheDir . DS . $thumbFile))
							$dataItem['thumb']['url'] = $cacheUri . '/' . $thumbFile;
					}
				}

				if ($navThumbImagePath && file_exists($navThumbImagePath) && is_readable($navThumbImagePath))
				{
					$thumbSize = getimagesize($navThumbImagePath);
					$dataItem['nav'] = array(
						'url' => str_replace(DS, '/', $folder . DS . str_replace('{$fileName}', $baseFileName, $navThumbPath)),
						'w' => $thumbSize[0],
						'h' => $thumbSize[1]
					);
				}
				else
				{
					$thumbSize = AriImageHelper::getThumbnailDimension($filePath, $navThumbWidth, $navThumbHeight, $thumbBehavior);
					$dataItem['nav'] = array(
						'url' => $fileUri,
						'w' => $thumbSize['w'],
						'h' => $thumbSize['h']
					);

					if ($thumbSize['w'] && $thumbSize['h'])
					{
						$thumbFile = AriImageHelper::generateThumbnailFileName($prefix, $filePath, $thumbSize['w'], $thumbSize['h'], $thumbType);
						if (@file_exists($cacheDir . DS . $thumbFile))
							$dataItem['nav']['url'] = $cacheUri . '/' . $thumbFile;
					}
				}

				if (isset($descriptions[$baseFileName]))
				{
					$dataItem = array_merge($descriptions[$baseFileName], $dataItem);
					$inCSV = true;
				}
				/*
				if ($emptyTitle && empty($dataItem['Title']))
				{
					$title = $emptyTitle;
					if ($needProcessEmptyTitle)
					{
						$pathInfo = pathinfo($baseFileName);
						
						$title = AriSimpleTemplate::parse(
							$title, 
							array(
								'fileName' => $baseFileName,
								'baseFileName' => basename($baseFileName, '.' . $pathInfo['extension'])
							)
						);
					}
					
					$dataItem['Title'] = $title;
				}
				*/
				$key = $this->getDataItemKey($filePath, $baseFileName, $sortBy, $inCSV);
				if (empty($key))
					$folderData[$baseFileName] = $dataItem;
				else
					$folderData[$key] = $dataItem;
			}
			
			if (count($folderData) == 0)
				continue ;
				
			if ($inCSV && $sortBy == 'csv')
			{
				$tempData = array();
				
				foreach ($descriptions as $fileName => $value)
				{
					if (!isset($folderData[$fileName]))
						continue ;
						
					$tempData[] = $folderData[$fileName];
					unset($folderData[$fileName]);
				}
				
				if ($sortDir == 'desc')
					$tempData = array_reverse($tempData);

				$folderData = array_values($folderData);
				$folderData = array_merge($tempData, array_values($folderData));
			}
			else if ($sortBy != 'filename' && $sortBy != 'modified')
			{
				$folderData = array_values($folderData);
			}
				
			$data = array_merge($data, $folderData);
		}
		
		if ($sortBy && $sortBy != 'random' && $sortBy != 'csv')
		{
			if ($sortDir == 'asc')
				ksort($data);
			else
				krsort($data); 
		}

		return $data;
	}
	
	function getDataItemKey($file, $baseFileName, $sortBy)
	{
		$key = null;
		switch ($sortBy)
		{
			case 'filename':
				$key = $baseFileName . md5($file);
				break;
				
			case 'modified':
				$key = filemtime($file) . md5($file);
				break;
		}
		
		return $key;
	}
	
	function getDescriptions($fileName, $path)
	{
		$data = array();
		$filePath = AriAppUtils::getLocalizedFileName($path . DS . $fileName);

		if (empty($fileName) || @!file_exists($filePath) || !@is_readable($filePath))
			return $data;

		$csvParser = new AriCSVParser();
		$csvParser->auto($filePath);
		$csvData = $csvParser->data;
		
		if (!empty($csvData))
		{
			foreach ($csvData as $csvDataItem)
			{
				if (isset($csvDataItem['File']))
					$data[$csvDataItem['File']] = $csvDataItem;
			}
		}

		return $data;
	}

	function generateThumbnails($params)
	{
		$thumbWidth = $params['thumbWidth'];
		$thumbHeight = $params['thumbHeight'];
		$folders = $params['folders'];
		$cacheDir = $this->_cacheDir;
		$prefix = $this->_prefix;
		$thumbPath = $params['thumbPath'];
		$thumbType = $params['thumbType'];
		$thumbTypeParams = $params['thumbTypeParams'];
		$thumbFilters = $params['thumbFilters'];
		
		$navThumbWidth = $params['navThumbWidth'];
		$navThumbHeight = $params['navThumbHeight'];
		$navThumbPath = $params['navThumbPath'];

		foreach ($folders as $folder)
		{
			$files = $this->getImageFiles($folder, $params['fileFilter']);
			foreach ($files as $file)
			{
				$filePath = JPATH_ROOT . DS . $file;
				$thumbImagePath = null;
				if ($thumbPath)
					$thumbImagePath = JPATH_ROOT . DS . $folder . DS . str_replace('{$fileName}', basename($file), $thumbPath);

				if (is_null($thumbImagePath) || !file_exists($thumbImagePath))
					AriImageHelper::generateThumbnail(
						$filePath, 
						$cacheDir, 
						$prefix, 
						$thumbWidth, 
						$thumbHeight,
						$thumbType,
						$thumbTypeParams,
						$thumbFilters
					);

				$thumbImagePath = null;
				if ($navThumbPath)
					$thumbImagePath = JPATH_ROOT . DS . $folder . DS . str_replace('{$fileName}', basename($file), $navThumbPath);

				if (is_null($thumbImagePath) || !file_exists($thumbImagePath))
				{
					AriImageHelper::generateThumbnail(
						$filePath, 
						$cacheDir, 
						$prefix, 
						$navThumbWidth, 
						$navThumbHeight,
						$thumbType,
						$thumbTypeParams,
						$thumbFilters
					);
				}
			}
		}
	}

	function getImageFiles($folder, $filter = '\.(jpg|gif|jpeg|png|bmp|JPG|GIF|JPEG|BMP)$')
	{
		return JFolder::files($folder, $filter, false, true);
	}

	function getCorrectedParameters($params)
	{
		$thumbWidth = intval(AriUtils::getParam($params, 'thumbWidth', 0), 10);
		if ($thumbWidth < 0) 
			$thumbWidth = 0;

		$thumbHeight = intval(AriUtils::getParam($params, 'thumbHeight', 0), 10);
		if ($thumbHeight < 0) 
			$thumbHeight = 0;

		$navThumbWidth = intval(AriUtils::getParam($params, 'navThumbWidth', 0), 10);
		if ($navThumbWidth < 0) 
			$navThumbWidth = 0;

		$navThumbHeight = intval(AriUtils::getParam($params, 'navThumbHeight', 0), 10);
		if ($navThumbHeight < 0) 
			$navThumbHeight = 0;
			
		$cachePeriod = intval(AriUtils::getParam($params, 'cachePeriod', 0), 10);
		if ($cachePeriod < 0) 
			$cachePeriod = 0;
		
		$generateThumbs = (($thumbWidth || $thumbHeight) && AriAsidoHelper::isExtensionLoaded())
			? AriUtils::parseValueBySample(AriUtils::getParam($params, 'generateThumbs'), false)
			: false;

		$scanSubFolders = AriUtils::parseValueBySample(AriUtils::getParam($params, 'subdir'), false);
		$folders = $this->getFolders(trim(AriUtils::getParam($params, 'dir', '')), $scanSubFolders);

		$thumbPath = trim(AriUtils::getParam($params, 'thumbPath', ''));
		if ($thumbPath)
			$thumbPath = preg_replace('#^[/\\\\]+|[/\\\\]+$#', '', JPath::clean($thumbPath));
			
		$navThumbPath = trim(AriUtils::getParam($params, 'navThumbPath', ''));
		if ($navThumbPath)
			$navThumbPath = preg_replace('#^[/\\\\]+|[/\\\\]+$#', '', JPath::clean($navThumbPath));

		$sortDir = strtolower(AriUtils::getParam($params, 'sortDir', 'asc'));
		if (!in_array($sortDir, array('asc', 'desc')))
			$sortDir = 'asc';

		$thumbType = strtolower(AriUtils::getParam($params, 'thumbType', 'resize'));
		if (!in_array($thumbType, array('resize', 'crop', 'cropresize')))
			$thumbType = 'resize';
			
		$thumbTypeParamKey = 'thumbType' . ucfirst($thumbType);
		$thumbTypeParams = AriUtils::getParam($params, $thumbTypeParamKey, array());

		return array(
			'key' => $params['key'],
			'checkSum' => $params['checkSum'],
			'descrFile' => trim(AriUtils::getParam($params, 'descrFile', '')),
			'fileFilter' => $params['fileFilter'],
			'thumbWidth' => $thumbWidth,
			'thumbHeight' => $thumbHeight,
			'generateThumbs' => $generateThumbs,
			'thumbType' => $thumbType,
			'thumbTypeParams' => $thumbTypeParams,
			'thumbFilters' => AriUtils::getParam($params, 'thumbFilters', array()),
			'folders' => $folders,
			'cachePeriod' => $cachePeriod,
			'thumbPath' => $thumbPath,

			'navThumbWidth' => $navThumbWidth,
			'navThumbHeight' => $navThumbHeight,
			'navThumbPath' => $navThumbPath,

			'sortDir' => $sortDir,
			'sortBy' => strtolower(AriUtils::getParam($params, 'sortBy', ''))
		);
	}

	function getFolders($folders, $scanSubFolders = true)
	{
		$findFolders = array();
		if (empty($folders))
			return $findFolders;
			
		$folders = str_replace(array("\r","\n"), array('',';'), $folders);
		$folders = explode(';', $folders);
		array_walk($folders, 'trim');
		foreach ($folders as $folder)
		{
			if (empty($folder) || !@file_exists($folder) || !@is_dir($folder))
				continue ;

			$folder = preg_replace('#^[/\\\\]+|[/\\\\]+$#', '', JPath::clean($folder));
			$findFolders[] = $folder;
			if ($scanSubFolders)
			{
				$subFolders = JFolder::folders($folder, '.', true, true);
				if (!empty($subFolders) && count($subFolders) > 0) $findFolders = array_merge($findFolders, $subFolders);
			}
		}

		return array_unique($findFolders);
	}
}