<?php
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Plugin uses custom tables and controlled internal query builders.
namespace SPAATG\Model\Image;

use SPAATG\Helper\DownloadHelper as DownloadHelper;
use SPAATG\Helper\UtilHelper as UtilHelper;


if (! defined('ABSPATH')) {
	exit; // Exit if accessed directly.
}

use SPAATG\ShortPixelLogger\ShortPixelLogger as Log;

use \SPAATG\Model\File\FileModel as FileModel;

// Represent a thumbnail image / limited image in mediaLibrary.
class MediaLibraryThumbnailModel extends \SPAATG\Model\Image\ImageModel
{

	public $name;

	/*  public $width;
  public $height;
  public $mime; */
	protected $prevent_next_try = false;
	protected $is_main_file = false;
	protected $is_retina = false; // diffentiate from thumbnail / retina.
	protected $id; // this is the parent attachment id
	protected $size; // size name of image in WP, if applicable.
	protected $sizeDefinition; // size width / height / crop according to WordPress

	public function __construct($path, $id, $size)
	{

		parent::__construct($path);
		$this->image_meta = new ImageThumbnailMeta();
		$this->id = $id;
		$this->imageType = self::IMAGE_TYPE_THUMB;
		$this->size = $size;
	}


	protected function loadMeta() {}

	protected function saveMeta() {}

	// Implementing this because it's abstract. Should not really be used.
	public function getParent()
	{
		return $this->getMainFile()->getParent();
	}

	public function __debugInfo()
	{
		return array(
			'image_meta' => $this->image_meta,
			'name' => $this->name,
			'path' => $this->getFullPath(),
			'size' => $this->size,
			'width' => $this->get('width'),
			'height' => $this->get('height'),
			'exists' => ($this->exists()) ? 'yes' : 'no',
			'is_virtual' => ($this->is_virtual()) ? 'yes' : 'no',
			'wordpress_size' => $this->sizeDefinition,

		);
	}

	/** Set the meta name of thumbnail. */
	public function setName($name)
	{
		$this->name = $name;
	}

	public function setSizeDefinition($sizedef)
	{
		$this->sizeDefinition = $sizedef;
	}

	public function setImageType($type)
	{
		$this->imageType = $type;
	}

	public function getRetina()
	{
		if ($this->is_virtual()) {
			$fs = \wpSPAATG()->filesystem();
			$filepath = apply_filters('spaatg/file/virtual/translate', $this->getFullPath(), $this);
			$virtualFile = $fs->getFile($filepath);

			$filebase = $virtualFile->getFileBase();
			$filepath = (string) $virtualFile->getFileDir();
			$extension = $virtualFile->getExtension();

			// This function needs an hard check on file exists, which might not be wanted.
			if (false === \wpSPAATG()->env()->useVirtualHeavyFunctions()) {
				return false;
			}
		} else {
			$filebase = $this->getFileBase();
			$filepath = (string) $this->getFileDir();
			$extension = $this->getExtension();
		}

		$retina = new MediaLibraryThumbnailModel($filepath . $filebase . '@2x.' . $extension, $this->id, $this->size); // mind the dot in after 2x
		$retina->setName($this->size);
		$retina->setImageType(self::IMAGE_TYPE_RETINA);

		$retina->is_retina = true;

		$forceCheck = true;
		if ($retina->exists($forceCheck))
			return $retina;

		return false;
	}

	public function isFileTypeNeeded($type = 'webp')
	{
		// pdf extension can be optimized, but don't come with these filetypes
		if ($this->getExtension() == 'pdf') {
			return false;
		}

		if ($type == 'webp')
			$file = $this->getWebp();
		elseif ($type == 'avif')
			$file = $this->getAvif();

		if (($this->isThumbnailProcessable() || $this->isOptimized()) && $file === false)  // if no file, it can be optimized.
			return true;
		else
			return false;
	}

	// @param FileDelete can be false. I.e. multilang duplicates might need removal of metadata, but not images.
	public function onDelete($fileDelete = true)
	{
		if ($fileDelete == true) {
			$bool = parent::onDelete();
		} else {
			$bool = true;
		}

		// minimally reset all the metadata.
		if ($this->is_main_file) {
			$this->image_meta = new ImageMeta();
		} else {
			$this->image_meta = new ImageThumbnailMeta();
		}

		return $bool;
	}



	protected function setMetaObj($metaObj)
	{
		$this->image_meta = clone $metaObj;
	}

	protected function getMetaObj()
	{
		return $this->image_meta;
	}

	// get_path param see MediaLibraryModel
	// This should be unused at the moment!
	public function getOptimizeUrls()
	{
		if (! $this->isProcessable())
			return false;

		$url = $this->getURL();

		if (! $url) {
			return false; //nothing
		}

		return $url;
	}

	public function getURL()
	{
		$fs = \wpSPAATG()->filesystem();

		if ($this->size == 'original' && ! $this->get('is_retina')) {
			$url = wp_get_original_image_url($this->id);
		} elseif ($this->isUnlisted()) {
			$url = $fs->pathToUrl($this);
		} else {
			// So get it from intermediate and if that doesn't work, default to pathToUrl - better than nothing.
			// https://app.asana.com/0/1200110778640816/1202589533659780
			$size_array = image_get_intermediate_size($this->id, $this->size);

			if ($size_array === false || ! isset($size_array['url'])) {
				$url = $fs->pathToUrl($this);
			} elseif (isset($size_array['url'])) {
				$url = $size_array['url'];
				// Even this can go wrong :/
				if (strpos($url, $this->getFileName()) === false) {
					// Taken from image_get_intermediate_size if somebody still messes with the filters.
					$mainurl = wp_get_attachment_url($this->id);
					$url = path_join(dirname($mainurl), $this->getFileName());
				}
			} else {
				return false;
			}
		}

		return $this->fs()->checkURL($url);
	}

	// Just a placeholder for abstract, shouldn't do anything.
	public function getImprovements()
	{
		return parent::getImprovements();
	}

	protected function preventNextTry($reason = '')
	{
		$this->prevent_next_try = $reason;
	}

	// Don't ask thumbnails this, only the main image
	public function isOptimizePrevented()
	{
		return false;
	}

	// Don't ask thumbnails this, only the main image
	public function resetPrevent()
	{
		return null;
	}

	protected function isThumbnailProcessable()
	{
		// if thumbnail processing is off, thumbs are never processable.
		// This is also used by main file, so check for that!

		if ($this->excludeThumbnails() && $this->is_main_file === false && $this->get('imageType') !== self::IMAGE_TYPE_ORIGINAL) {
			$this->processable_status = self::P_EXCLUDE_SIZE;
			return false;
		} else {
			$bool = parent::isProcessable();

			return $bool;
		}
	}

	/** Function to check if said thumbnail is a WP-native or something SPAATG added as unlisted
	 *
	 *
	 */
	protected function isUnlisted()
	{
		if (! is_null($this->getMeta('file')))
			return true;
		else
			return false;
	}



	// !Important . This doubles as  checking excluded image sizes.
	protected function isSizeExcluded()
	{

		$excludeSizes = \wpSPAATG()->settings()->excludeSizes;

		if (is_array($excludeSizes) && in_array($this->name, $excludeSizes)) {
			$this->processable_status = self::P_EXCLUDE_SIZE;
			return true;
		}

		$bool = parent::isSizeExcluded();

		return $bool;
	}




	public function isProcessableFileType($type = 'webp')
	{
		// Prevent webp / avif processing for thumbnails if this is off. Exclude main file
		if ($this->excludeThumbnails() === true && $this->is_main_file === false)
			return false;

		return parent::isProcessableFileType($type);
	}

	protected function getExcludePatterns()
	{
		$args = array(
			'filter' => true,
			'thumbname' => $this->name,
			'is_thumbnail' => (true === $this->is_main_file) ? false : true,
		);

		// @todo Find a way to cache IsProcessable perhaps due to amount of checks being done.  Should be release in flushOptimizeCache or elsewhere (?)

		//    $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);

		$patterns = UtilHelper::getExclusions($args);
		//  echo "<PRE>"; print_r($args); print_r($patterns); echo "</PRE>";
		return $patterns;
	}

	protected function excludeThumbnails()
	{
		return (! \wpSPAATG()->settings()->processThumbnails);
	}

	public function hasDBRecord()
	{
		return false;
	}

	public function restore()
	{
		return false;
	}

	// @todo This is a breach of pattern to realize checking for changes to the main image path on conversion / duplicates.
	private function getMainFile()
	{
		$fs = \wpSPAATG()->filesystem();
		return $fs->getMediaImage($this->id, true, true);
	}
} // class
