#!/bin/bash
#-------------------------------------------------------------------
#		EXPERT SOLUTIONS SARL
#		convert_clariprint_php_to_js.sh
#		Convert Clariprint php files to js files for SugarcrepeHLUX
#		To execute with bash : bash convert_clariprint_php_to_js.sh
#		-x option to vizualize command line
#-------------------------------------------------------------------

echo "*******************************************"
echo "#1 clean current the directory rm -rf *.js"
rm -rf *.js

echo "#2 create temp .js file by extract lines of .php files between //<HLUX> & //</HLUX> tags"

	# get array number of line match //<[/]?HLUX>
getHLUX="//<[/]?HLUX>"
GREPRESULT=( $(ls -1 *.php | xargs -i@ grep -E -H -n "${getHLUX}" @ ) )

echo ${GREPRESULT[@]}

currentFile=""
currentIndex=0

for nl in ${GREPRESULT[@]};
do
	declare -a lineArray
	lineArray=($(echo $nl | tr ":" "\n"))
	echo "parse line '${nl} : ${lineArray[@]}', currentFile:'${currentFile}'"
	lineFile="${lineArray[0]}"
	lineIndex=$(("${lineArray[1]}" + 0))
	lineTag="${lineArray[2]}"
	
	matchEndTag=$(echo "${lineTag}" | grep -c -a "</HLUX>")
	
	echo "file:'$lineFile' index:$lineIndex tag:$matchEndTag"

	if [ "$currentFile" = "" ];
	then
		echo "touch ${lineFile}.js"
		currentIndex=$(($lineIndex + 0))
		echo "set currIndex:$currentIndex"
		touch "${lineFile}.js"
		currentFile=$lineFile

	elif [ "$currentFile" = "$lineFile" ] && [ "$matchEndTag" =	"1" ];
	then
		echo "match end tag so append line from:$currentIndex to:$lineIndex"
		#getting part of source file from currentIndex to lineIndex
		n=0
		_ifs=$IFS
		IFS="" # set IFS to "" to maintain indentation
		while read line; 
		do
			n=$((n+1))
			if [ $lineIndex -gt $n ] && [ $currentIndex -lt $n ];
			then 
				# echo "#$n:append" # >> "${currentFile}.HLUX"
				# reading each good line then append to .HLUX file
				echo "$line" >> "${currentFile}.js"
			fi
		done < $currentFile
		IFS=$_ifs # restore IFS
	elif [ "$currentFile" = "$lineFile" ] && [ "$matchEndTag" = "0" ];
	then 
		currentIndex=$(($lineIndex + 0))
		echo "MAJ currIndex:$currentIndex"
	else 
		currentFile="$lineFile"
		echo "next file:'$currentFile'"
		currentIndex=0
	fi
done

echo "*******************************************"
echo "#3 convert .js files from php language to js"

	# shortcut for charsets match[] and get()
s="[ \t]" 						# space | tab
sn="[ \t\n]"
w="a-zA-Z_0-9" 					# \w seems not work for sed !!! it needs perl extension for regex
								# A-B define A to B charset 
eDol="\\\$"						# $ is parse by bash so we have to escape it : \$ => \\\$
CSObjProp="][$eDol,$w,\,-\.,>"		# carefull ][ must be used at the start of charset 
matchProp="[$CSObjProp]+"		# [charset] + for once or more * for 0 or more ? for 0 or once
matchPropExt="$matchProp+->?$matchProp?->?$matchProp?->?$matchProp?->?$matchProp"
#getProp="($matchPropExt)"			# (content) assign the content to \1 \2 .. \9 in replacement regex
getProp="($matchProp)"			# (content) assign the content to \1 \2 .. \9 in replacement regex
getPropModifier="([$CSObjProp\|]+)"
CSString="$w -><;\.:,'\""
CSStringLight="$w \,-\.><;:"
CSSTranslate="$CSStringLight%"
CSSTranslateModifer="$CSSTranslate\|"
CSRegex="][\\\s\\\w\\\W\, ;\+\*\/$w,-><;\.:" # /[\s, ;]+/
CSMath="\+\*\-\/"
CSMultiline="$CSString\n"
matchString="[$CSString]*"
CSvarname="-$w"
getVarName="['\"]?([$CSvarname]*)['\"]?" # ['"]? are optionnal in smarty
CScompare="!=<>| "
CScall="\(\)\, "
CSFile="-$w\.\/"
matchFile="[$CSFile]*"
getFile="($matchFile)"
CSsomething="$CSObjProp $CScall $CSString"
matchSomething="[$CSsomething]*"
getSomething="($matchSomething)"

SOptions=":a;N;\$!ba;"
# (:a;N;$!ba) read the whole file in a loop, then replaces the newline(s) # without it all regex with \n failded
# see https://stackoverflow.com/questions/1251999/how-can-i-replace-each-newline-n-with-a-space-using-sed

# concatenation
RX0=("([^0-9])\.([^0-9])" 	"\1\+\2"	"") 		# "." is concatenation operator in php replace by "+" in js

# class extend toto
RX1=("class$s+([$w]+)$s+extends$s+([$w]+)($sn*)\{" 	"class \1_PHP extends \2_PHP\3\{\n\tconstructor\(\) \{\n\t\tsuper();\n\/\/<constructor:\1>\n\n\/\/<\/constructor:\1>\n\t\}" 	$SOptions)
RX2=("private$s+$getProp"					"\#\1" 		"")
RX3=("public$s+function$s+"					""			"")
RX4=("static$s+function$s+"				"static "			"")
#RX4=("function"								""			"")
RX5=("self::" 								"this\."	"")
RX6=("\\\$this" 								"this"		"")


# foreach
RX10=("foreach\(([$CSObjProp$CScall$CSString=>\t]*)\)($sn+)\{([^{}]*)\}"	"foreach\(\1\)\2µ\3£"	$SOptions)
RX11=("if$s*\(([$CSObjProp$CScall$CSString$CScompare=>\t]*)\)($sn+)\{([^{}]*)\}"		"if \(\1\)\2§\3\^"		$SOptions)
RX12=("foreach\(([$CSObjProp$CScall$CSString=>\t]*)\)($sn+)\{([^{}]*)\}"	"foreach\(\1\)\2µ\3£"	$SOptions)
RX13=("if$s*\(([$CSObjProp$CScall$CSString$CScompare=>\t]*)\)($sn+)\{([^{}]*)\}"		"if \(\1\)\2§\3\^"		$SOptions)
RX14=("foreach\(([$CSObjProp$CScall$CSString$=>\t]*)\)($sn+)\{([^{}]*)\}"	"foreach\(\1\)\2µ\3£"	$SOptions)
RX15=("if$s*\(([$CSObjProp$CScall$CSString$CScompare=>\t]*)\)($sn+)\{([^{}]*)\}"		"if \(\1\)\2§\3\^"		$SOptions)

RX16=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*=>$s*$getProp$s*\)($sn*)µ([^µ£]*)£" "Object.entries(\1).forEach\(entry =<> \{ const \[\2, \3] = entry;\4\5}\);" $SOptions)
RX17=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*\)($sn*)µ([^µ£]*)£" "\1.forEach\(\2 =<>\3\{\4}\);" $SOptions)
RX18=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*\)($sn*)([^µ£]*);" "\1.forEach\(\2 =<>\3\{\4}\);" "")

RX19=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*=>$s*$getProp$s*\)($sn*)µ([^µ£]*)£" "Object.entries(\1).forEach\(entry =<> \{ const \[\2, \3] = entry;\4\5}\);" $SOptions)
RX20=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*\)($sn*)µ([^µ£]*)£" "\1.forEach\(\2 =<>\3\{\4}\);" $SOptions)

RX21=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*=>$s*$getProp$s*\)($sn*)µ([^µ£]*)£" "Object.entries(\1).forEach\(entry =<> \{ const \[\2, \3] = entry;\4\5}\);" $SOptions)
RX22=("foreach\($s*([$CSObjProp$CScall]+)$s+as$s+$getProp$s*\)($sn*)µ([^µ£]*)£" "\1.forEach\(\2 =<>\3\{\4}\);" $SOptions)

RX23=("§" 	"{" 	"")
RX24=("\^" 	"}"		"")

matchETButPRTS="[^(-)]*"
# array
RX30=("([^y])\(([^()]*)\)"				"\1µ\2£"	"")	# replace () of anything except array()
RX31=("([^y])\(([^()]*)\)"				"\1µ\2£"	"")	# replace () of anything except array()
RX32=("([\n\t ;()]+)array\(($matchETButPRTS)\)"	"\1§\2\^"		$SOptions)	# replace array(...) finaux by §...§
RX33=("([^y])\(($matchETButPRTS)\)"		"\1µ\2£"	"")	# replace () of anything except array()
RX34=("([\n\t ;()]+)array\(($matchETButPRTS)\)"	"\1§\2\^"		$SOptions)	# replace array(...) finaux by §...§
RX35=("([^y])\(($matchETButPRTS)\)"		"\1µ\2£"	"")	# replace () of anything except array()
RX36=("([\n\t ;()]+)array\(($matchETButPRTS)\)"	"\1§\2\^"		$SOptions)	# replace array(...) finaux by §...§

RX37=("§([^=§^]*)\^"			"\[\1\]"		$SOptions)		# replace §...§ qui ne contient pas de = par [...]
RX38=("([§\,]$sn*)([^§\,=^]+)=>([^§\,=^]+)([\,\^])"	"\1\2:\3\4"		$SOptions)
RX39=("([§\,]$sn*)([^§\,=^]+)=>([^§\,=^]+)([\,\^])"	"\1\2:\3\4"		$SOptions)
RX40=("([§\,]$sn*)([^§\,=^]+)=>([^§\,=^]+)([\,\^])"	"\1\2:\3\4"		$SOptions)

RX41=("§([^§^]*:[^§^]*)\^"				"\{\1\}"		$SOptions)		
RX42=("§([^=§^]*)\^"					"\[\1\]"		$SOptions)		# replace §...§ qui ne contient pas de = par [...]
RX43=("([§\,]$sn*)([^§\,=^]+)=>([^\,=§^]+)([\,\^])"	"\1\2:\3\4"		$SOptions)
RX44=("([§\,]$sn*)([^§\,=^]+)=>([^\,=§^]+)([\,\^])"	"\1\2:\3\4"		$SOptions)
RX45=("([§\,]$sn*)([^§\,=^]+)=>([^\,=§^]+)([\,\^])"	"\1\2:\3\4"		$SOptions)

RX57=("§([^§^]*:[^§^]*)\^"				"\{\1\}"		$SOptions)		
RX58=("§([^=§^]*)\^"			"\[\1\]"		$SOptions)		# replace §...§ qui ne contient pas de = par [...]

#RX59=("§([^§^]*)\^"				"\{\1\}"		$SOptions)		

RX60=("µ([^µ£]*)£"	"\(\1\)"	$SOptions)	# restore () for anything except array
RX61=("µ([^µ£]*)£"	"\(\1\)"	"")	# restore () for anything except array
RX62=("µ([^µ£]*)£"	"\(\1\)" 	"")	# restore () for anything except array
RX63=("µ([^µ£]*)£"	"\(\1\)"	"")	# restore () for anything except array

RX65=("$getProp\[\]$s*=$s*([$CSObjProp$CScall$CSString]+)$s*;"	"\1.push\(\2\);"	"")

RX66=("=<>" "=>" "")
#RX6=("array\(([^=]*)\)" "\[\1\]")
#RX7=("(=>$s+)array\(([$CSObjProp$CScall$CSString=]+)\)"	"\1\{\2\}")
#RX8=("array\([]\)"	"\{\1\}")

# main functions
RX70=("explode\($s*([$CSObjProp,$CSMultiline]*)$s*\,$s*$getProp$s*\)" 			"\2\.split\(\1\)"		"")
RX71=("in_array\($s*$getProp$s*\,$s*$getProp$s*\)" 						"\2\.includes\(\1\)"	"")
RX72=("in_array\($s*$getVarName$s*\,$s*$getProp$s*\)"					"\2\.includes\('\1\')"	"")
RX73=("count\($s*$getProp$s*\)" 												"\1\.length"			"")
RX74=("end\($s*$getProp$s*\)" 													"\1\.at(-1)"			"")
RX75=("isset\($s*$getProp$s*\)" 												"\1 !== undefined"		"")

# cast and type 
RX80=("\(int\)\(?$s*$getProp($s*[$CSMath]+$s*[0-9]*$s*)\)?"						"parseInt\(\1\,10\)\2"	"")
RX81=("\(int\)(\($s*)?$getProp($s*\))?"											"parseInt\(\2\,10\)"	"")
RX82=("is_object\($s*$getProp$s*\)"												"typeof \1 == 'object'"	"")

# symbols
RX91=("->($eDol[$w]+)" 		"\[\1\]"	"") 	
RX92=("->([$w]+)" 			"\.\1"		"")
RX93=(" != " 				" !== "		"")
RX94=("&$s*$eDol"	"$eDol"	"")
RX95=("elseif" "else if" "")
RX99=("([$w]+)::([$w]+)"	"\1.\2"	"")
RX100=("\/\/JS" "" "")

#rm -rf *.js
#mkdir ejs

#cp *.tpl ejs/
#cd ejs
#rename "s/.tpl/.ejs/" *.tpl
ls -1 *.js

echo "create regex script"

for rxi in {0..100};
#for rxi in {5..5};
do
	snam="RX$rxi[0]"
	if [ "${!snam}" != "" ] ;
 	then 
 		rnam="RX$rxi[1]"
 		opts="RX$rxi[2]"
		echo \#$rxi search "s/${!snam}/"
		echo \#$rxi replace by "${!rnam}/g"
		for fil in $(ls -1 *.js)
		do 
			echo sed -r -E -i "${!opts}s/${!snam}/${!rnam}/g" $fil
			sed -r -E -i "${!opts}s/${!snam}/${!rnam}/g" $fil
		done
	fi
done


echo --------------------------------
echo "end step #3"
ls -al

rm *.sed

echo "#4 extract members vars declarations in source.class.vars files"
getVars="//<[/]?var:"
GREPRESULT=( $(ls -1 *.js | xargs -i@ grep -E -H -n "${getVars}" @ ) )

echo ${GREPRESULT[@]}

currentFile=""
currentIndex=0

for nl in ${GREPRESULT[@]};
do
	declare -a lineArray
	lineArray=($(echo $nl | tr "[:>]" "\n"))
	echo "parse line '${nl} : ${lineArray[@]}', currentFile:'${currentFile}'"
	lineFile="${lineArray[0]}"
	lineIndex=$(("${lineArray[1]}" + 0))
	lineTag="${lineArray[2]}"
	lineClass="${lineArray[3]}"

	matchEndTag=$(echo "${lineTag}" | grep -c -a "</var")
	
	echo "file:'$lineFile' index:$lineIndex endtag:$matchEndTag class:$lineClass"

	if [ "$currentFile" = "" ];
	then
		echo "touch ${lineFile}.${lineClass}.sed"
		currentIndex=$(($lineIndex + 0))
		echo "set currIndex:$currentIndex"
		touch "${lineFile}.${lineClass}.sed"
		printf %s%s "${SOptions}" "s/\/\/<constructor:Clariprint>[\n\t ]*\/\/<\/constructor:Clariprint>/" >> "${lineFile}.${lineClass}.sed"
		currentFile=$lineFile

	elif [ "$currentFile" = "$lineFile" ] && [ "$matchEndTag" =	"1" ];
	then
		echo "match end tag so append line from:$currentIndex to:$lineIndex"
		#getting part of source file from currentIndex to lineIndex
		n=0
		_ifs=$IFS
		IFS="" # set IFS to "" to maintain indentation
		while read line; 
		do
			n=$((n+1))
			if [ $lineIndex -gt $n ] && [ $currentIndex -lt $n ];
			then 
				# echo "#$n:append" # >> "${currentFile}.HLUX"
				# reading each good line then append to .HLUX file
				echo $line
				escapeLine=($(echo $line 		| sed -E "s/var$s+([$])/this./g"))
				escapeLine=($(echo $escapeLine	| sed -E "s/([][])/\\\\\1/g"))
				escapeLine=($(echo $escapeLine 	| sed -E "s/([{}])/\\\\\1/g"))
				escapeLine=($(echo $escapeLine 	| sed -E "s/([,])/\\\\\1/g"))
				escapeLine=($(echo $escapeLine 	| sed -E "s/([$])/\\\\\1/g"))
#				escapeLine=($(echo $escapeLine 	| sed "s/([}])/\\\1/"))
				echo $escapeLine
				printf "\\\n%s" "$escapeLine" >> "${currentFile}.${lineClass}.sed"
			fi
		done < $currentFile
		IFS=$_ifs # restore IFS
	elif [ "$currentFile" = "$lineFile" ] && [ "$matchEndTag" = "0" ];
	then 
		currentIndex=$(($lineIndex + 0))
		echo "MAJ currIndex:$currentIndex"
	else 
		currentFile="$lineFile"
		echo "next file:'$currentFile'"
		currentIndex=0
	fi
done

echo "#5 foreach source foreach class read sources.class.sed file with sed to put declaration in constructor"
for srcFile in $(ls -1 *.js)
do
	for sedFile in $(ls -1 $srcFile.*.sed)
	do 
			echo sed -r -E -i -f $sedFile $srcFile
			printf %s "/g" >> $sedFile
			sed -r -E -i -f $sedFile $srcFile
	done
done

echo "#6 foreach .php.js file clean //<var tag"
for srcFile in $(ls -1 *.js)
do
#		sed -E -i "${SOptions}s/\/\/<var:[$w]+>[$CSObjProp=:; $CScompare$CScall\n\t'\"{}]*\/\/<\/var:[$w]+>/\n/g" $srcFile
		sed -E -i "${SOptions}s/\/\/<var:[$w]+>[^<>]*\/\/<\/var:[$w]+>/\n/g" $srcFile
done