<?php
namespace App\Utils\BaseParser\Utils;

/**
 * Match wildcard(*)
 */

class WildcardMatcher
{
	use \App\Utils\BaseParser\SingletonTrait;

	/**
	 * Match wildcard
	 *
	 * @param string $elementToBeMatched
	 * @param array $patternsList
	 * @throws \Exception\Regexp\Base
	 * @return boolean
	 */
	public function matchList(string $elementToBeMatched, array $patternsList)
	{
		/* Please have a look on fnmatch($pattern, $string)
		 * http://php.net/manual/en/function.fnmatch.php
		 */
		$tmpWildcardReplacement = "__WILDCARD_REPLACEMENT__";
		foreach ($patternsList as $pattern) {
			/**
			 * replace "*" with "__ANY__". DO NOT REPLACE ESCAPED '\*'
			 * Ex:
			 * 	input:	 *@\*\\*.com
			 *		  (.+)@\*\\*.com
			 * 	output: __XYZ_ANY__@*\*.com
			 * So we'd be able to use str_replace below (for __XYZ_ANY__, and it will ignore \*)
			 **/
			$regexp = preg_replace('/(?<!\\\\)\\*/', $tmpWildcardReplacement, $pattern);
			if ($regexp === null) {	// check for regexp error
				throw new \Exception\Regexp\Base(sprintf("[%s] Invalid regexp generated for pattern: '%s'", __METHOD__, $pattern));
			}

			// quote all special chars
			$regexp = preg_quote($regexp, "/");

			// replace '\*' with '*', replace "__ANY__" with regexp equivalent
			$regexp = str_replace(['\\\\*', $tmpWildcardReplacement, ], ['*', '(.+)', ], $regexp);

			// check if we actually have a match
			$matched = preg_match("/^{$regexp}$/i", $elementToBeMatched);
			if ($matched === false) {	// check for regexp error
				throw new \Exception\Regexp\Base(sprintf("[%s] Invalid regexp: '%s'", __METHOD__, $regexp));
			}

			if ($matched === 1) {	// short-circuit the whole loop, we already matched something
				return true;
			}
		}

		// nothing matched
		return false;
	}
}
