<?php

/**
* @package   s9e\TextFormatter
* @copyright Copyright (c) 2010-2023 The s9e authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\TextFormatter\Plugins\Litedown\Parser\Passes;

use s9e\TextFormatter\Plugins\Litedown\Parser\LinkAttributesSetter;

class Images extends AbstractPass
{
	use LinkAttributesSetter;

	/**
	* {@inheritdoc}
	*/
	public function parse()
	{
		$pos = $this->text->indexOf('![');
		if ($pos === false)
		{
			return;
		}
		if ($this->text->indexOf('](', $pos) !== false)
		{
			$this->parseInlineImages();
		}
		if ($this->text->hasReferences)
		{
			$this->parseReferenceImages();
		}
	}

	/**
	* Add an image tag for given text span
	*
	* @param  integer $startPos Start tag position
	* @param  integer $endPos   End tag position
	* @param  integer $endLen   End tag length
	* @param  string  $linkInfo URL optionally followed by space and a title
	* @param  string  $alt      Value for the alt attribute
	* @return void
	*/
	protected function addImageTag($startPos, $endPos, $endLen, $linkInfo, $alt)
	{
		$tag = $this->parser->addTagPair('IMG', $startPos, 2, $endPos, $endLen);
		$this->setLinkAttributes($tag, $linkInfo, 'src');
		$tag->setAttribute('alt', $this->text->decode($alt));

		// Overwrite the markup
		$this->text->overwrite($startPos, $endPos + $endLen - $startPos);
	}

	/**
	* Parse inline images markup
	*
	* @return void
	*/
	protected function parseInlineImages()
	{
		preg_match_all(
			'/!\\[(?:[^\\x17[\\]]|\\[[^\\x17[\\]]*\\])*\\]\\(( *(?:[^\\x17\\s()]|\\([^\\x17\\s()]*\\))*(?=[ )]) *(?:"[^\\x17]*?"|\'[^\\x17]*?\'|\\([^\\x17)]*\\))? *)\\)/',
			$this->text,
			$matches,
			PREG_OFFSET_CAPTURE | PREG_SET_ORDER
		);
		foreach ($matches as $m)
		{
			$linkInfo = $m[1][0];
			$startPos = $m[0][1];
			$endLen   = 3 + strlen($linkInfo);
			$endPos   = $startPos + strlen($m[0][0]) - $endLen;
			$alt      = substr($m[0][0], 2, strlen($m[0][0]) - $endLen - 2);

			$this->addImageTag($startPos, $endPos, $endLen, $linkInfo, $alt);
		}
	}

	/**
	* Parse reference images markup
	*
	* @return void
	*/
	protected function parseReferenceImages()
	{
		preg_match_all(
			'/!\\[((?:[^\\x17[\\]]|\\[[^\\x17[\\]]*\\])*)\\](?: ?\\[([^\\x17[\\]]+)\\])?/',
			$this->text,
			$matches,
			PREG_OFFSET_CAPTURE | PREG_SET_ORDER
		);
		foreach ($matches as $m)
		{
			$startPos = $m[0][1];
			$endPos   = $startPos + 2 + strlen($m[1][0]);
			$endLen   = 1;
			$alt      = $m[1][0];
			$id       = $alt;

			if (isset($m[2][0], $this->text->linkReferences[$m[2][0]]))
			{
				$endLen = strlen($m[0][0]) - strlen($alt) - 2;
				$id        = $m[2][0];
			}
			elseif (!isset($this->text->linkReferences[$id]))
			{
				continue;
			}

			$this->addImageTag($startPos, $endPos, $endLen, $this->text->linkReferences[$id], $alt);
		}
	}
}