<?php

class AVForums_Competitions_Helper_Image
{
	protected  $_origImage = null;
	protected $_image = null;

	protected $_imageType = 0;

	protected $_origWidth = 0;
	protected $_origHeight = 0;

	protected $_resizeWidth = 0;
	protected $_resizeHeight = 0;

	protected $_borderWidth = 0;
	protected $_borderColour = array();

	/**
	 * Constructor.
	 *
	 * @param string $filename of the image to manipulate
	 */
	public function __construct($filename)
	{
		if (file_exists($filename))
		{
			$this->_setImage($filename);
		}
		else
		{
			throw new Zend_Exception('Image ' . $filename . ' can not be found, try another image.');
		}
	}

	/**
	 * Sets the image variable.
	 *
	 * @param string $filename of the image to manipulate
	 * @param integer $imageType IMAGETYPE_XYZ constant representing image type
	 *
	 */
	protected function _setImage($filename, $imageType = null)
	{
		$this->_imageType = $imageType;

		if ($this->_imageType === null)
		{
			if (function_exists('exif_imagetype'))
			{
				$this->_imageType = exif_imagetype($filename);
			}
			else
			{
				$size = getimagesize($filename);
				$this->_imageType = $size[2];
			}
		}

		$invalidType = false;

		try
		{
			switch ($this->_imageType)
			{
				case IMAGETYPE_GIF:
					$this->_image = @imagecreatefromgif($filename);
					break;

				case IMAGETYPE_JPEG:
					$this->_image = @imagecreatefromjpeg($filename);
					break;

				case IMAGETYPE_PNG:
					$this->_image = @imagecreatefrompng($filename);
					break;

				default:
					$invalidType = true;
			}
		}
		catch (Exception $e)
		{
			return false;
		}

		if ($invalidType)
		{
			throw new XenForo_Exception('Invalid image type given. Expects IMAGETYPE_XXX constant.');
		}

		$this->_origWidth = imagesx($this->_image);
		$this->_origHeight = imagesy($this->_image);
		$this->_origImage = $this->_image;
	}

	/**
	 * Saves the image to the specified path.
	 *
	 * @param string $savePath of the image
	 * @param string $imageQuality of the saved image
	 */
	public function saveImage($savePath, $imageQuality = 100, $download = false)
	{
		$invalidType = false;
		try
		{
			imageinterlace($this->_image, true);

			switch ($this->_imageType)
			{
				case IMAGETYPE_GIF:
					imagegif($this->_image, $savePath);
					break;

				case IMAGETYPE_JPEG:
					imagejpeg($this->_image, $savePath, $imageQuality);
					break;

				case IMAGETYPE_PNG:
					$invertScaleQuality = 9 - round(($imageQuality / 100) * 9);

					imagepng($this->_image, $savePath, $invertScaleQuality);
					break;

				default:
					$invalidType = true;
			}
		}
		catch (Exception $e)
		{
			return false;
		}

		if ($invalidType)
		{
			throw new XenForo_Exception('Invalid image type given. Expects IMAGETYPE_XXX constant.');
		}

		if ($download)
		{
			header ('Content-Description: File Transfer');
			header ("Content-type: application/octet-stream");
			header ("Content-disposition: attachment; filename= " . $savePath . "");
			readfile ($savePath);
		}

		imagedestroy($this->_image);
	}

	/**
	 * Resize the image to the specified dimensions
	 *
	 * @param  int $width Max width of the image
	 * @param  int $height Max height of the image
	 * @param  string $resizeOption - Scale option for the image
	 */
	public function resizeTo($width, $height, $resizeOption = 'default')
	{
		switch($resizeOption)
		{
			case 'exact':
				$this->_resizeWidth = $width;
				$this->_resizeHeight = $height;
				break;

			case 'maxwidth':
				$this->_resizeWidth  = $width;
				$this->_resizeHeight = $this->_resizeHeightByWidth($width);
				break;

			case 'maxheight':
				$this->_resizeWidth  = $this->_resizeWidthByHeight($height);
				$this->_resizeHeight = $height;
				break;

			default:
				if($this->_origWidth > $width || $this->_origHeight > $height)
				{
					if ( $this->_origWidth > $this->_origHeight )
					{
						$this->_resizeHeight = $this->_resizeHeightByWidth($width);
						$this->_resizeWidth  = $width;
					}
					else if( $this->_origWidth < $this->_origHeight )
					{
						$this->_resizeWidth  = $this->_resizeWidthByHeight($height);
						$this->_resizeHeight = $height;
					}
				}
				else
				{
					$this->_resizeWidth = $width;
					$this->_resizeHeight = $height;
				}
				break;
		}

		$this->_newImage = imagecreatetruecolor($this->_resizeWidth, $this->_resizeHeight);

		$background = imagecolorallocate($this->_newImage, 0, 0, 0);

		imagecolortransparent($this->_newImage, $background);
		imagealphablending($this->_newImage, false);
		imagesavealpha($this->_newImage, true);

		imagecopyresampled($this->_newImage, $this->_image, 0, 0, 0, 0, $this->_resizeWidth, $this->_resizeHeight, $this->_origWidth, $this->_origHeight);

		$this->_image = $this->_newImage;
	}

	/**
	 * Resize and crop the image to the specified dimensions
	 *
	 * @param  int $width Max width of the image
	 * @param  int $height Max height of the image
	 * @param  int $x Max width of the image
	 * @param  int $y Max height of the image
	 * @param  int $sourceWidth Max width of the image
	 * @param  int $sourceHeight Max height of the image
	 */
	public function resizeCrop($width = 0, $height = 0, $x = 0, $y = 0, $sourceWidth = 0, $sourceHeight = 0)
	{
		$this->_newImage = imagecreatetruecolor($width, $height);

		$background = imagecolorallocate($this->_newImage, 0, 0, 0);

		imagecolortransparent($this->_newImage, $background);
		imagealphablending($this->_newImage, false);
		imagesavealpha($this->_newImage, true);
		
		if (!$sourceWidth || !$sourceHeight)
		{
			$sourceWidth = $this->_origWidth;
			$sourceHeight = $this->_origHeight;
		}

		imagecopyresampled($this->_newImage, $this->_image, 0, 0, $x, $y, $width, $height, $sourceWidth, $sourceHeight);

		$this->_image = $this->_newImage;
	}

	/**
	 * Get the resized height from the width keeping the aspect ratio
	 *
	 * @param  int $width - Max image width
	 *
	 * @return Height keeping aspect ratio
	 */
	protected function _resizeHeightByWidth($width)
	{
		return floor(($this->_origHeight / $this->_origWidth) * $width);
	}

	/**
	 * Get the resized width from the height keeping the aspect ratio
	 *
	 * @param  int $height - Max image height
	 *
	 * @return Width keeping aspect ratio
	 */
	protected function _resizeWidthByHeight($height)
	{
		return floor(($this->_origWidth / $this->_origHeight) * $height);
	}
}