@echo OFF
setlocal enabledelayedexpansion

reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=x86 || set OS=x64

cls
echo ---------------------------------------
echo --- unipatch v0.8 by epithetic --------
echo ---------------------------------------
echo.
echo.
if %1.==. goto MissingParam
if %2.==. goto MissingParam

rem Version info (tag installers for compatibility support should need arise)
set unipver=UNIP0.8

set "source=%1"
set "dest=%2"
set "work=%~dp0%"

if not exist !source!\ goto MissingDir
if not exist !dest!\ goto MissingDir

rem Get name & desc to display when installing
set "unipname=noname"
set /p unipname=Enter an ID for your installer (no spaces): 
set "unipreq=█"
set /p unipreq=Enter prerequisite patch IDs in install order (separated by spaces): 
set "uniptitle=Untitled"
set /p uniptitle=Enter a descriptive title for your installer: 
set "unipdesc=No description."
set /p unipdesc=Enter a short description for your installer: 

rem Housekeeping
if not exist !unipname!-unip\ ( mkdir !unipname!-unip )
rem if exist unipatch-log.txt ( del unipatch-log.txt )
if exist !unipname!-unip\!unipname!-unip.remap (del !unipname!-unip\!unipname!-unip.remap)
if exist !unipname!-unip\!unipname!-unip.info (del !unipname!-unip\!unipname!-unip.info)
set warncount=0
set errcount=0

echo.

echo Preparing to create installer !unipname!-unip...
echo.

echo ---------------------------------------- >> unipatch-log.txt
echo %time% %date% ^| Preparing to create installer !unipname!-unip... >> unipatch-log.txt
echo ---------------------------------------- >> unipatch-log.txt
echo. >> unipatch-log.txt


rem Remove spaces from paths so it's easier to wrangle relative paths
set work_=!work: =█!
set dest_=!dest: =█!
set work_=!work_:"=!
set dest_=!dest_:"=!
set source_=!source: =█!
set source_=!source_:"=!

rem Main loop, iterate through files in destination directory
for /R %dest%\ %%i in (*) do (
	set "fullpath=%%i"
	set "pathonly=%%~fi"
	set "filename=%%~nxi"
	rem Replace spaces to make these easier to work with.
	set fullpath_=!fullpath: =█!
	set pathonly_=!pathonly: =█!
	set filename_=!filename: =█!
	rem Generate the corresponding unpatched file path and output
	call:ReplaceText !pathonly_! !work_! "" destpath_
	call:ReplaceText !destpath_! !dest_!\ !source_!\ sourcepath_
	rem Make sure diff directory exists
	call:ReplaceText !destpath_! !dest_!\ !unipname!-unip\!source_!\ patchfullpath_
	call:ReplaceText !patchfullpath_! !filename_! "" patchpath_
	
	rem echo !destpath_! from !sourcepath_!
	rem echo !filename!
	
	rem regenerate actual paths
	set "sourcepath=!sourcepath_:█= !"
	set "destpath=!destpath_:█= !"
	set "patchpath=!patchpath_:█= !"
	
	if not exist !patchpath! ( mkdir "!patchpath!" )
	
	rem check if files are identical
	set skipidentical=0
	if exist !sourcepath! (
		fc /b "!sourcepath!" "!destpath!" > nul
		if errorlevel 1 (
			rem files are different, continue
		) else (
			set /a warncount+=1
			echo Warning: File !destpath! identical to base file. Skipping.
			rem log identical to file
			echo WARNING: !fullpath! identical to !sourcepath!. Skipping. >> unipatch-log.txt
			set skipidentical=1
		)
	)
	
	rem check if diff file needs to be remapped
	if not exist !sourcepath! (
		:PromptManual
		echo Warning: File !destpath! does not have a patchable base file. Provide manual target. ^(skip = skip^)
		set choice=""
		set "source=!source:█= !"
		set prompt_=!source_!\
		set "prompt=!prompt_:█= !"
		set /p choice=!prompt!
		if !choice! == skip (
			rem manually skipped
			echo Skipping.
			rem log skip to file and treat as identical
			echo WARNING: !fullpath! did not have a patchable base file. Skipping. >> unipatch-log.txt
			set skipidentical=1
			set /a warncount+=1
		) else if not exist !source!\!choice! (
			echo "!choice!" is not valid, try again
			echo.
			goto PromptManual
		) else if !choice! == "" (
			echo "Enter a replacement file to diff."
			echo.
			goto PromptManual
		) else (
			set choice_=!choice: =█!
			set sourcepath_=!source_!\!choice_!
			set filename_=@!filename_!
			echo !patchpath_!!filename_!.hdiff !sourcepath_! >> !unipname!-unip\!unipname!-unip.remap
			rem log missing to file
			echo WARNING: !fullpath! was remapped to !sourcepath_!. >> unipatch-log.txt
			set /a warncount+=1
		)
		
	)
	
	rem regenerate actual paths
	set "sourcepath=!sourcepath_:█= !"
	set "destpath=!destpath_:█= !"
	set output_=!patchpath_!!filename_!.hdiff
	set "output=!output_:█= !"
	
	rem generate diff file
	if !skipidentical! == 0 (
		if exist !output! ( del "!output!" ) 
		bin\!OS!\hdiffz.exe -m-1 -cache -SD -c-bzip2 "!sourcepath!" "!destpath!" "!output!" >> unipatch.tmp
		type unipatch.tmp >> unipatch-log.txt
		rem Did hdiffz succeed?
		>nul find "patch check diff data ok" unipatch.tmp && (
		  echo Processed !destpath! successfully.
		) || (
		  echo ERROR in processing !destpath!, check unipatch-log.txt
		  set /a errcount+=1
		)
		del unipatch.tmp
	)
)

rem Write version, name & desc to info file
echo !unipver! >> !unipname!-unip\!unipname!-unip.info
echo !uniptitle! >> !unipname!-unip\!unipname!-unip.info
echo !unipdesc! >> !unipname!-unip\!unipname!-unip.info
if !unipreq! == █ (
	echo.>> !unipname!-unip\!unipname!-unip.info
) else (
	echo !unipreq! >> !unipname!-unip\!unipname!-unip.info
)

rem Remove empty directories left over
for /f "delims=" %%d in ('dir !unipname!-unip /s /b /ad ^| sort /r') do ( rd /q "%%d" > nul 2>&1 )

echo.
echo Finished generating installer !unipname!-unip with !warncount! warnings and !errcount! errors.

goto End

:MissingParam
echo Please specify an original and patched directory: build-unip.bat sourcedir destdir.
echo ^(use program's root directory to maximise compatibility with other patches^)
goto End

:MissingDir
echo One or both of the specified directories do not exist.
goto End

:End
goto :eof

:ReplaceText
::Replace Text In String
::USE:
:: CALL:ReplaceText "!OriginalText!" OldWordToReplace NewWordToUse  Result
set "OriginalText=%~1"
set "OldWord=%~2"
set "NewWord=%~3"
call set OriginalText=%%OriginalText:!OldWord!=!NewWord!%%
SET %4=!OriginalText!
Goto End