;-- TIME_STAMP   2018-07-16 19:48:19   v 0.1

;*****************************************
;Mustache.au3 by Churanos
;Created with ISN AutoIt Studio v. 1.07
;*****************************************
#include-once
#include <Array.au3>
#include <StringConstants.au3>

Const $__g_iMustache_OK = 0
Const $__g_iMustache_ERROR_SYSTEM = -1
Const $__g_iMustache_ERROR_UNEXPECTED_END = -2
Const $__g_iMustache_ERROR_EMPTY_TAG = -3
Const $__g_iMustache_ERROR_TAG_TOO_LONG = -4
Const $__g_iMustache_ERROR_BAD_SEPARATORS = -5
Const $__g_iMustache_ERROR_TOO_DEPTH = -6
Const $__g_iMustache_ERROR_CLOSING = -7
Const $__g_iMustache_ERROR_BAD_UNESCAPE_TAG = -8

Global $__g_sMustache_REGEX_Partial = "(?im)({{\>([\w\d]+)}})"
Global $__g_sMustache_REGEX_Section = "(?im)({{\#([\w\d]+)}})([\W\w\d\s]+)({{\/\2}})"
Global $__g_sMustache_REGEX_InvertedSection = "(?im)({{\^([\w\d]+)}})([\W\w\d\s]+)({{\/\2}})"
Global $__g_sMustache_REGEX_Variable = "(?im)({{([\w\d]+)}})"
Global $__g_sMustache_REGEX_UnescapedVariable = "(?im)({{\&([\w\d]+)}})"
Global $__g_sMustache_REGEX_Comment = "(?im)({{\![\w\d\s]+}})"

Global $__g_oMustache_EscapeChars = __Mustache_Dict(False)
$__g_oMustache_EscapeChars.Add("&", "&amp;")
$__g_oMustache_EscapeChars.Add("<", "&lt;")
$__g_oMustache_EscapeChars.Add(">", "&gt;")
$__g_oMustache_EscapeChars.Add('"', "&qout;")
$__g_oMustache_EscapeChars.Add("'", "&#39;")
$__g_oMustache_EscapeChars.Add("/", "&#x2F;")



; #FUNCTION# ====================================================================================================================
; Name ..........: _Mustache_Render
; Description ...:
; Syntax ........: _Mustache_Render($sTemplatePath, ByRef $vData [, $oPartials = __Mustache_Dict()])
; Parameters ....: $sTemplatePath       - A string value.
;                  ByRef $vData         - An unknown value.
;                  $oPartials           - [optional] A object value. Default is __Mustache_Dict().
; Return values .: None
; Author ........: Churanos
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _Mustache_Render($sTemplatePath, ByRef $vData, $oPartials = __Mustache_Dict())
	Local $data = ObjCreate("Scripting.Dictionary")
	$data.CompareMode = 1

	#Region Comments
	Local $asComments = StringRegExp($sTemplatePath, $__g_sMustache_REGEX_Comment, $STR_REGEXPARRAYGLOBALFULLMATCH)
	If @error Then
		$data.Add("comments", __Mustache_Array())
	Else
		$data.Add("comments", $asComments)
	EndIf

	For $item In ($data("comments"))
		$sTemplatePath = StringReplace($sTemplatePath, $item[0], "", 1)
	Next
	#EndRegion Comments


	#Region Partials
	Local $asPartials = StringRegExp($sTemplatePath, $__g_sMustache_REGEX_Partial, $STR_REGEXPARRAYGLOBALFULLMATCH)
	If @error Then
		$data.Add("partials", __Mustache_Array())
	Else
		$data.Add("partials", $asPartials)
	EndIf

	For $item In ($data("partials"))
		If $oPartials.Exists($item[2]) Then
			$sTemplatePath = StringReplace($sTemplatePath, $item[1], _Mustache_Render($oPartials($item[2]), $vData, $oPartials))
		Else
			ConsoleWrite("Partial " & $item[2] & " not found!" & @CRLF)
		EndIf
	Next
	#EndRegion Partials


	#Region Inverted Sections
	Local $asInvertedSections = StringRegExp($sTemplatePath, $__g_sMustache_REGEX_InvertedSection, $STR_REGEXPARRAYGLOBALFULLMATCH)
	If @error Then
		$data.Add("inverted_sections", __Mustache_Array())
	Else
		$data.Add("inverted_sections", $asInvertedSections)
	EndIf

	For $item In ($data("inverted_sections"))
		If $vData($item[2]) = False Then
			$sTemplatePath = StringReplace($sTemplatePath, $item[0], _Mustache_Render($item[3], $vData, $oPartials))
		ElseIf UBound($vData($item[2])) <= 0 Then
			$sTemplatePath = StringReplace($sTemplatePath, $item[0], _Mustache_Render($item[3], $vData, $oPartials))
		Else

		EndIf
	Next
	#EndRegion Inverted Sections


	#Region Sections
	Local $asSections = StringRegExp($sTemplatePath, $__g_sMustache_REGEX_Section, $STR_REGEXPARRAYGLOBALFULLMATCH)
	If @error Then
		$data.Add("sections", __Mustache_Array())
	Else
		$data.Add("sections", $asSections)
	EndIf

	Local $sUserFunction, $sRes
	For $item In $data("sections")
		Switch VarGetType($vData($item[2]))
			Case "UserFunction"
				ConsoleWrite('+ $sTemplatePath = ' & $sTemplatePath & @CRLF & @CRLF)
				ConsoleWrite('- $vData($item[0]) = "' & $vData($item[0]) & '", VarGetType($vData($item[0])) = ' & VarGetType($vData($item[0])) & @CRLF & @CRLF)
				ConsoleWrite('- $vData($item[2]) = "' & $vData($item[2]) & '", VarGetType($vData($item[2])) = ' & VarGetType($vData($item[2])) & ', FuncName($vData($item[2])) = ' & FuncName($vData($item[2])) & @CRLF & @CRLF)
				ConsoleWrite('- $vData($item[3]) = "' & $vData($item[3]) & '", VarGetType($vData($item[3])) = ' & VarGetType($vData($item[3])) & @CRLF & @CRLF)

;~ 				$sTemplatePath = StringReplace($sTemplatePath, $item[0], ($vData($item[2]))($item[3], $vData)) ; AU3Check meckert!
;~ 				$sTemplatePath = StringReplace($sTemplatePath, $item[0], $vData($item[2])($item[3], $vData)) ; AU3Check meckert nicht, Funktion wird aber NICHT aufgerufen!

				; AU3Check meckert nicht, Funktion wird wie beabsichtigt aufgerufen!
				$sUserFunction = $vData($item[2])
				$sRes = $sUserFunction($item[3], $vData)
				$sTemplatePath = StringReplace($sTemplatePath, $item[0], $sRes)

				ConsoleWrite('! $item[0]       = ' & $item[0] & @CRLF & @CRLF)
				ConsoleWrite('! $sRes          = ' & $sRes & @CRLF & @CRLF)
				ConsoleWrite('! $sTemplatePath = ' & $sTemplatePath & @CRLF & @CRLF)
				_ArrayDisplay($item, '$item')
			Case "Array"
				Local $sTempString = ""
				For $tempData In ($vData[$item[2]])
					$sTempString &= _Mustache_Render($item[3], $tempData)
				Next
				$sTemplatePath = StringReplace($sTemplatePath, $item[1], $sTempString)
			Case "Object"
				$sTemplatePath = StringReplace($sTemplatePath, $item[1], _Mustache_Render($item[3], $vData[$item[2]]))
			Case Else
				If ($vData($item[2])) Then
					$sTemplatePath = StringReplace($sTemplatePath, $item[0], $item[3])
				Else
					$sTemplatePath = StringReplace($sTemplatePath, $item[0], "")
				EndIf
		EndSwitch
	Next
	#EndRegion Sections


	#Region Variables
	Local $asVariables = StringRegExp($sTemplatePath, $__g_sMustache_REGEX_Variable, $STR_REGEXPARRAYGLOBALFULLMATCH)
	If @error Then
		$data.Add("variables", __Mustache_Array())
	Else
		$data.Add("variables", $asVariables)
	EndIf

	For $item In ($data("variables"))
		Local $rep = $vData($item[2])
		For $esc In $__g_oMustache_EscapeChars.Keys
			$rep = StringRegExpReplace($rep, $esc, $__g_oMustache_EscapeChars($esc))
		Next
		$sTemplatePath = StringReplace($sTemplatePath, $item[1], $rep, 1)
	Next
	#EndRegion Variables


	#Region Unescaped Variables
	Local $asUnescapedVariables = StringRegExp($sTemplatePath, $__g_sMustache_REGEX_UnescapedVariable, $STR_REGEXPARRAYGLOBALFULLMATCH)
	If @error Then
		$data.Add("unescaped_variables", __Mustache_Array())
	Else
		$data.Add("unescaped_variables", $asUnescapedVariables)
	EndIf

	For $item In ($data("unescaped_variables"))
		$sTemplatePath = StringReplace($sTemplatePath, $item[1], $vData($item[2]), 1)
	Next
	#EndRegion Unescaped Variables



	Return $sTemplatePath
EndFunc   ;==>_Mustache_Render


Func __Mustache_Array()
	Local $arr[0]
	Return $arr
EndFunc   ;==>__Mustache_Array

Func __Mustache_Dict($bCompareMode = True)
	Local $dict = ObjCreate("Scripting.Dictionary")
	$dict.CompareMode = $bCompareMode ? 1 : 0
	Return $dict
EndFunc   ;==>__Mustache_Dict
