<?php

namespace Planaday\Html\Parsers;

use Planaday\Html\Nodes\NodeData;
use Planaday\Html\Parsers\DynamicDataParsers\DynamicDataParser;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\Debug\Log\Logging;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;

#[Scoped]
class StringInterpolationParser{
	use Logging;
	protected NodeData $nodeData;

	public function __construct(
		protected DynamicDataParser $dataParser,
		protected LocalizationController $loc
	) {
		$this->nodeData = new NodeData();
	}

	public function setNodeData( NodeData $data ): void {
		$this->nodeData = $data;
	}

	public function parse( string $html ): string {
		$replaceCallback = function($match) {
			$innerString = trim($match[1]);

			return match ( substr( $innerString, 0, 1 ) ) {
				"_" => $this->translate( substr( $innerString, 1 ) ),
				"?" => $this->solveConditional( $innerString ),
				default => $this->dataParser->parseForString( $innerString, $this->nodeData->data ),
			};
		};

		$html = preg_replace_callback("/\\{\\{(.+?)}}/", $replaceCallback, $html);

		return str_replace("\\{\\{", "{{", $html);
	}

	public function parseCode( string $html ): string {
		$replaceCallback = function($match) {
			$innerString = trim($match[1]);

			return match ( substr( $innerString, 0, 1 ) ) {
				"_" => $this->translate( substr( $innerString, 1 ) ),
				"?" => $this->solveConditional( $innerString ),
				default => $this->dataParser->parseForString( $innerString, $this->nodeData->data ),
			};
		};

		$html = preg_replace_callback( "#<!--\\{\\{(.+?)}}-->#", $replaceCallback, $html);
		$html = preg_replace_callback( "#/\\*\\{\\{(.+?)}}\\*/#", $replaceCallback, $html);
		$html = preg_replace_callback( "#padInjectData\[[\"']\{\{(.+?)}}[\"']]#", $replaceCallback, $html);

		return str_replace("\\{\\{", "{{", $html);
	}

	protected function translate(string $toTranslate): string{
		$toTranslate = trim($toTranslate);

		if ($this->isDataAddress($toTranslate)){
			$string = $this->dataParser->parseForString($toTranslate, $this->nodeData->data) ?? '';
		} else {
			$string = substr($toTranslate, 1, -1);
		}

		$classCausingTranslate = $this->nodeData->data['autoGenerated']['currentTag']['class'] ?? '';
		$templateCausingTranslate = $this->nodeData->data['autoGenerated']['currentTag']['template'] ?? '';
		return $this->loc->translate($string, "$classCausingTranslate:$templateCausingTranslate(template)");
	}

	protected function isDataAddress(string $value): bool {
		return !(preg_match("/^_?['\"].*['\"]$/", $value) === 1);
	}

	protected function solveConditional(string $conditional): string{
		if ( str_starts_with( $conditional, '??' ) ){
			return $this->solveNullConditional(substr($conditional, 2));
		}

		if(!preg_match("/^\\?([^?]+)\\?([^:]+):(.+)$/", $conditional, $matches)) {
			$this->logError( "invalid conditional string, cant parse data", $conditional );
			return '';
		}

		if ($this->dataParser->parseRaw(trim($matches[1]), $this->nodeData->data)){
			$result = trim($matches[2]);
		} else {
			$result = trim($matches[3]);
		}

		if ($this->isDataAddress($result)){
			return $this->dataParser->parseForString($result, $this->nodeData->data) ?? '';
		}

		if (str_starts_with($result, "_")){
			return $this->loc->translate(substr($result, 2, -1));
		} else {
			return substr($result, 1, -1);
		}
	}

	protected function solveNullConditional(string $conditional): string{
		$dataPoints = explode("??", $conditional);
		$result = '';

		foreach ($dataPoints as $dataPoint){
			$dataPoint = trim($dataPoint);

			if ($this->isDataAddress($dataPoint)){
				$result = $this->dataParser->parseForString($dataPoint, $this->nodeData->data);
			} else {
				if (str_starts_with($dataPoint, "_")){
					$result = $this->loc->translate(substr($dataPoint, 2, -1));
				} else {
					$result = substr($dataPoint, 1, -1);
				}
			}

			if (!empty($result)){
				return $result;
			}
		}

		return $result ?? '';
	}
}