<?php

namespace Planaday\Html\Tags;

use DOMNode;
use Planaday\Html\Tags\Admin\AdminTagHandler;
use Planaday\Html\Tags\Course\CourseTagsHandler;
use Planaday\Html\Tags\DayParts\DayPartsTagsHandler;
use Planaday\Html\Tags\Form\FormTagsHandler;
use Planaday\Html\Tags\Generic\GenericTagHandler;
use Planaday\Html\Tags\Mail\MailTagHandler;
use Planaday\Html\Tags\Platform\PlatformTagHandler;
use Planaday\Html\Tags\Test\TestTagHandler;
use Planaday\Html\Tags\Utility\UtilityTagHandler;
use Planaday\Platform\PlatformAbstraction\UserService;
use Planaday\Utility\Debug\Log\Logging;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;

class TagController {
	use Logging;
	/** @var TagHandlerTemplate[] */
	protected array $tagHandlers = [];

	/** @var array<callable(Container):Tag> */
	protected array $tags = [];

	/**
	 * @param Container $registry
	 * @param UserService $userService
	 */
	public function __construct(
		protected Container $registry,
		UserService $userService
	) {
		$this->registerHandlers($userService->isAdmin());
		$this->registerTags();
	}

	private function registerHandlers(bool $isAdmin): void{
		$this->tagHandlers = [
			new FormTagsHandler(),
			new DayPartsTagsHandler(),
			new TestTagHandler(),
			new CourseTagsHandler(),
			new GenericTagHandler(),
			new UtilityTagHandler(),
			new MailTagHandler(),
			new PlatformTagHandler()
		];

		if ($isAdmin) $this->tagHandlers[] = new AdminTagHandler();
	}

	private function registerTags(): void{
		foreach ($this->tagHandlers as $tagHandler){
			$this->tags = $tagHandler->registerTags($this->tags);
		}
		$this->logInfo('Registered ' . count($this->tags) . ' tags', array_keys($this->tags));
	}

	/**
	 * @param DOMNode $tagNode
	 *
	 * @return Tag
	 * @throws TagNotFoundException
	 * @throws InjectionImpossibleException
	 */
	public function getTag( DOMNode $tagNode): Tag{
		$tagName = str_replace('pad-', '', $tagNode->localName ?? '');

		if (($this->tags[$tagName] ?? null) === null) {
			$this->logError('Tag ' . $tagName . ' not found');
			throw new TagNotFoundException();
		}

		$this->logDebug('Tag ' . $tagName . ' found');
		return $this->tags[$tagName]($this->registry);
	}
}