<?php

namespace Planaday\Html\NodeTags;

use DOMElement;
use DOMNode;
use Planaday\Html\Nodes\NodeCouldNotBeCreatedException;
use Planaday\Html\Nodes\ParserNode;
use Planaday\Utility\Debug\Log\Logging;

trait InnerContentControl {
	use Logging;

	/**
	 * @param DOMElement&ParserNode $originalNode
	 *
	 * @return DOMElement&ParserNode
	 * @throws NodeCouldNotBeCreatedException
	 */
	protected function getInnerContentFragment( DOMElement&ParserNode $originalNode): DOMElement&ParserNode {
		$fragment = $originalNode->getUsableDocumentFragment();
		$copiedNode = $originalNode->cloneNode(true);
		$fragment->setExtendedNodeData( clone $originalNode->getExtendedNodeData() );

		for ($i = count($copiedNode->childNodes) - 1; $i >= 0; $i--) {
			$fragment->prepend($copiedNode->childNodes->item($i));
		}

		return $fragment;
	}

	protected function replaceContentTagWithinFragment( string $tagName, DOMElement&ParserNode $innerContent, DOMElement&ParserNode $fragment ): void {
		$currentElement = $fragment->lastElementChild;
		while ($currentElement !== null) {
			$nextElement = $currentElement->previousElementSibling;

			if ($currentElement->tagName === $tagName) {
				$this->logDebug("replacing tag: " . $currentElement->tagName);
				$currentElement->replaceWith($innerContent->cloneNode(true));
				$currentElement = $nextElement;
				continue;
			}

			$tagsWithName = $currentElement->getElementsByTagName($tagName);
			$this->logDebug("found " . $tagsWithName->length . " tags with name: " . $tagName);

			for ($i = $tagsWithName->length - 1; $i >= 0; $i--) {
				$tag = $tagsWithName->item($i);
				if ($tag === null) continue;
				if (!$this->nodeContainsNode($fragment, $tag)) continue;

				$this->logDebug("replacing tag: " . $tag->nodeName);
				$tag->replaceWith($innerContent->cloneNode(true));
			}

			$currentElement = $nextElement;
		}
	}

	protected function nodeContainsNode(DOMNode $node, DOMNode $childNode): bool {
		while (true){
			$parent = $childNode->parentNode;
			if ($parent === null) return false;
			if ($node->isSameNode($parent)) return true;
			$childNode = $parent;
		}
	}
}