<?php
define("TAG_PROCESSOR_PATH","Model/TagProcessors/");
include(TAG_PROCESSOR_PATH."ITagProcessor.php");

class PostFormatter{
	public static $TAG_MATCH_REGEX='@\[([a-z]*) ?(.*?)(\](.*?)\[)?/\1?\]@ms';
	
	private static $_content=array();
	private static $_randomIndexModifier="";
	
	private static function ParamsToArgs($params){
		$args=array();
		foreach ($params as $p){
			if (strpos($p, "=")===false)
				continue;
			$parts=explode("=",$p);
			$parts[1]=trim($parts[1],'"');
			$args[$parts[0]]=$parts[1];
		}
		return $args;
	}

	private static function ProcessTag($matches){
		$processorName=$matches[1];
		
		if (!file_exists(TAG_PROCESSOR_PATH.$processorName.".php"))
			return $matches[0];
		
		include_once(TAG_PROCESSOR_PATH.$processorName.".php");
		
		$class="\\Tags\\".$processorName;
		$processor=new $class;
		if (!($processor instanceof \Tags\ITagProcessor))
			return $matches[0];

		$params=array();
		if (isset($matches[2]))
			$params=explode(" ",trim($matches[2]));
		
		$content=null;
		if (isset($matches[4]))
			$content=self::GetProcessedString($matches[4]);
		
		$args=self::ParamsToArgs($params);
		$result=call_user_func("\\Tags\\".$processorName."::Process",$args,$content);
		if ($result!==FALSE){
			$index=count(self::$_content);
			self::$_content[$index]=$result;
			return '{{'.self::$_randomIndexModifier.$index.'}}';
		}
		
		return $matches[0];
	}
	
	private static function GetProcessedString($string){
		return preg_replace_callback(self::$TAG_MATCH_REGEX,"self::ProcessTag", $string);
	}
	
	private static function PopulateString($matches){
		if (!isset($matches[1]))
			return $matches[0];
		
		$index=(int)$matches[1];
		if (!isset(self::$_content[$index]))
			return $matches[0];
		
		$str=self::ProcessPopulateString(self::$_content[$index]);
		return $str;
	}
	
	private static function ProcessPopulateString($string){
		$str=preg_replace_callback('/\{\{'.self::$_randomIndexModifier.'(\d+)\}\}/', "self::PopulateString", $string);
		return $str;
	}

	public static function FormatToHTML($str){
		self::$_content=array();
		self::$_randomIndexModifier=Utils::GenerateRandomString();

		$str=self::GetProcessedString($str);
		$str=str_replace("\r", '', $str);
		$strParts=explode("\n\n", $str);
		$returnStr="";
		foreach ($strParts as $s){
			$s=trim($s);
			if ($s=="")
				continue;
			
			$s=htmlentities($s);
			$s=self::GetProcessedString($s);
			$s=nl2br($s);
			$returnStr.="<p>$s</p>";
		}
		
		$returnStr=self::ProcessPopulateString($returnStr);
		return $returnStr;
	}
	
	public static function CloseOpenTag($str){
		$matches=array();
		preg_match_all('@.*\[([a-z]*) ?[^/]*?\](.*)$@ms', $str, $matches); //(?![\[/\1\]])
		
		if (count($matches[0])==0 || preg_match_all('@\[/'.$matches[1][0].'\]@', $matches[2][0])>0)
			return $str;
		
		$closeTag='[/'.$matches[1][0].']';
		return $str.PHP_EOL.$closeTag;
	}
}