<?php
/*****************************************************************************
 * Image.php
 * Contains key class Image.
 *
 * Kabuki CMS (C) 2013-2015, Aaron van Geffen
 *****************************************************************************/

class Image extends Asset
{
	const TYPE_PANORAMA = 1;
	const TYPE_LANDSCAPE = 2;
	const TYPE_PORTRAIT = 4;

	protected function __construct(array $data)
	{
		foreach ($data as $attribute => $value)
			$this->$attribute = $value;
	}

	public static function fromId($id_asset, $return_format = 'object')
	{
		$asset = parent::fromId($id_asset, 'array');
		if ($asset)
			return $return_format == 'object' ? new Image($asset) : $asset;
		else
			return false;
	}

	public static function fromIds(array $id_assets, $return_format = 'object')
	{
		if (empty($id_assets))
			return [];

		$assets = parent::fromIds($id_assets, 'array');

		if ($return_format == 'array')
			return $assets;
		else
		{
			$objects = [];
			foreach ($assets as $id => $asset)
				$objects[$id] = new Image($asset);
			return $objects;
		}
	}

	public function save()
	{
		$data = [];
		foreach ($this->meta as $key => $value)
			$data[] = [
				'id_asset' => $this->id_asset,
				'variable' => $key,
				'value' => $value,
			];

		return Registry::get('db')->insert('replace', 'assets_meta', [
			'id_asset' => 'int',
			'variable' => 'string',
			'value' => 'string',
			], $data);
	}

	public function getExif()
	{
		return EXIF::fromFile($this->getPath());
	}

	public function getPath()
	{
		return ASSETSDIR . '/' . $this->subdir . '/' . $this->filename;
	}

	public function getUrl()
	{
		return ASSETSURL . '/' . $this->subdir . '/' . $this->filename;
	}

	/**
	 * @param width: width of the thumbnail.
	 * @param height: height of the thumbnail.
	 * @param crop: whether and how to crop original image to fit. [false|true|'top'|'center'|'bottom']
	 * @param fit: whether to fit the image to given boundaries [true], or use them merely as an estimation [false].
	 * @param generate: whether or not to generate a thumbnail if no existing file was found.
	 */
	public function getThumbnailUrl($width, $height, $crop = true, $fit = true, $generate = false)
	{
		$thumbnail = new Thumbnail($this);
		return $thumbnail->getUrl($width, $height, $crop, $fit, $generate);
	}

	public function getId()
	{
		return $this->id_asset;
	}

	public function width()
	{
		return $this->image_width;
	}

	public function height()
	{
		return $this->image_height;
	}

	public function ratio()
	{
		return $this->image_width / $this->image_height;
	}

	public function isPanorama()
	{
		return $this->ratio() >= 2;
	}

	public function isPortrait()
	{
		return $this->ratio() < 1;
	}

	public function isLandscape()
	{
		$ratio = $this->ratio();
		return $ratio >= 1 && $ratio <= 2;
	}

	public function getThumbnails()
	{
		return $this->thumbnails;
	}

	public function removeAllThumbnails()
	{
		foreach ($this->thumbnails as $key => $filename)
		{
			$thumb_path = THUMBSDIR . '/' . $this->subdir . '/' . $filename;
			if (is_file($thumb_path))
				unlink($thumb_path);
		}

		return Registry::get('db')->query('
			DELETE FROM assets_thumbs
			WHERE id_asset = {int:id_asset}',
			['id_asset' => $this->id_asset]);
	}

	public function removeThumbnailsOfSize($width, $height)
	{
		foreach ($this->thumbnails as $key => $filename)
		{
			if (strpos($key, $width . 'x' . $height) !== 0)
				continue;

			$thumb_path = THUMBSDIR . '/' . $this->subdir . '/' . $filename;
			if (is_file($thumb_path))
				unlink($thumb_path);
		}

		return Registry::get('db')->query('
			DELETE FROM assets_thumbs
			WHERE id_asset = {int:id_asset} AND
				width = {int:width} AND
				height = {int:height}',
			[
				'height' => $height,
				'id_asset' => $this->id_asset,
				'width' => $width,
			]);
	}

	public function replaceThumbnail($descriptor, $tmp_file)
	{
		if (!is_file($tmp_file))
			return -1;

		if (!isset($this->thumbnails[$descriptor]))
			return -2;

		$image = new Imagick($tmp_file);
		$d = $image->getImageGeometry();
		unset($image);

		// Check whether dimensions match.
		$test_descriptor = $d['width'] . 'x' . $d['height'];
		if ($descriptor !== $test_descriptor && strpos($descriptor, $test_descriptor . '_') === false)
			return -3;

		// Save the custom thumbnail in the assets directory.
		$destination = ASSETSDIR . '/' . $this->subdir . '/' . $this->thumbnails[$descriptor];
		if (file_exists($destination) && !is_writable($destination))
			return -4;

		if (!copy($tmp_file, $destination))
			return -5;

		// Copy it to the thumbnail directory, overwriting the automatically generated one, too.
		$destination = THUMBSDIR . '/' . $this->subdir . '/' . $this->thumbnails[$descriptor];
		if (file_exists($destination) && !is_writable($destination))
			return -6;

		if (!copy($tmp_file, $destination))
			return -7;

		// A little bookkeeping
		$this->meta['custom_' . $d['width'] . 'x' . $d['height']] = $this->thumbnails[$descriptor];
		$this->saveMetaData();
		return 0;
	}
}