<?php

namespace Planaday\Html\Parsers;

use DOMNode;
use Planaday\Html\Nodes\NodeCouldNotBeCreatedException;
use Planaday\Html\Nodes\NodeData;
use Planaday\Html\Nodes\ParserNode;
use Planaday\Html\Nodes\StdParserElement;
use Planaday\Html\NodeTags\TagNotFullyInitializedException;
use Planaday\Html\Parsers\NodeParsers\TagMarkers\TestDataTag;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;

#[Scoped]
class BlockParser extends StdDOMParser {
	protected function doNode(DOMNode&ParserNode $node, NodeData $nodeData): void {
		$this->logDebug("starting Node: " . $node->nodeName);
		$nodeData = $node->getExtendedNodeData() ?? $nodeData;
		$node->setExtendedNodeData($nodeData);

		if ($node instanceof StdParserElement){
			$this->prepareElement($node, $nodeData);
		}

		foreach ($this->nodeParsers as $nodeParser){
			$nodeParser->setNodeData($nodeData);
			$nodeParser->modifyNode($node);
		}

		$tag = $node->getAssociatedTag();
		if ($node instanceof StdParserElement){
			if ($node->tagName === "document-fragment") {
				$this->logDebug("Node is document-fragment, preparing...");
				try {
					$newNode = $node->getAsDocumentFragment();
				} catch ( NodeCouldNotBeCreatedException $e ) {
					$comment = $node->ownerDocument->createComment( "node could not be created: " . $e->getMessage() );
					$node->prepend( $comment );
				}
			}

			if ($tag !== null){
				try{
					$tag->setNodeData($nodeData);
					if ($tag instanceof TestDataTag) $tag->injectTestData();
					$this->logDebug("Node is associated with tag, running: " . get_class($tag));
					$newNode = $tag->getNewNode();
				} catch (NodeCouldNotBeCreatedException|TagNotFullyInitializedException $e){
					$comment = $node->ownerDocument->createComment("Tag was not initialized: " . $e->getMessage());
					$node->prepend($comment);
				}
			}
		}

		$this->logDebug("Node is done: " . $node->nodeName);

		$this->doChildNodes($node, $nodeData);
		if (isset($newNode)){
			$this->doChildNodes($newNode, $nodeData);
		}

		if ($node instanceof StdParserElement && isset($newNode)){
			if ($newNode instanceof StdParserElement){
				try {
					$newNode = $newNode->getAsDocumentFragment();
				} catch (NodeCouldNotBeCreatedException) {}
			}

			$this->logDebug("Replacing Node: " . $node->tagName);
			$node->replaceWith($newNode);
		}
	}
}