; === Languages ===
LoadLanguageFile "${NSISDIR}\Contrib\Language files\French.nlf"

; === Program Details ===
Caption "${APPNAME} Portable | PerkedleApps"
VIProductVersion "${APPVER}"
VIAddVersionKey /LANG=${LANG_FRENCH} BuildDate "${BUILDDATE} ${__TIME__}"
VIAddVersionKey /LANG=${LANG_FRENCH} ProductName "${APPNAME} Portable"
VIAddVersionKey /LANG=${LANG_FRENCH} Comments "Allows ${APPNAME} to be run from a removable drive."
VIAddVersionKey /LANG=${LANG_FRENCH} CompanyName "PerkedleApps"
VIAddVersionKey /LANG=${LANG_FRENCH} LegalCopyright "Azure Zanculmarktum"
VIAddVersionKey /LANG=${LANG_FRENCH} FileDescription "${APPNAME} Portable"
VIAddVersionKey /LANG=${LANG_FRENCH} FileVersion "${APPVER}"
VIAddVersionKey /LANG=${LANG_FRENCH} ProductVersion "${VER}"
VIAddVersionKey /LANG=${LANG_FRENCH} InternalName "${APPNAME}"
VIAddVersionKey /LANG=${LANG_FRENCH} LegalTrademarks "PerkedleApps is a Trademark of Azure Zanculmarktum"
VIAddVersionKey /LANG=${LANG_FRENCH} OriginalFilename "${APP}Portable.exe"

; === Runtime Switches ===
XPStyle on
CRCCheck on
WindowIcon off
!ifndef CUSTOMUI & NOUI
	SilentInstall silent
!endif
!ifdef CUSTOMUI & NOUI
	!error "both CUSTOMUI and NOUI are defined"
!endif
!ifdef CUSTOMUI | NOUI
	SubCaption 3 " "
	SubCaption 4 " "
	CompletedText " "
!endif
!ifdef CUSTOMUI
	ChangeUI all Include\customUI.bin
!endif
!ifdef NOUI
	ChangeUI all Include\noUI.bin
!endif
AutoCloseWindow true
!ifndef RUNASADMIN
	RequestExecutionLevel user
!else
	RequestExecutionLevel admin
!endif

; === Include ===
!include TextFunc.nsh
!insertmacro GetParameters
!include FileFunc.nsh
!insertmacro GetRoot
!include LogicLib.nsh
!include Include\SystemMessageBox.nsh

; === Additional Plug-ins ===
!addplugindir Plugins

; === Default Variables ===
Var PROGRAMDIR
!ifdef APPDIR64
	Var PROGRAMDIR64
!endif
Var PROGRAMEXE
!ifdef APPEXE64
	Var PROGRAMEXE64
!endif
Var DEFAULTDATA
Var SETTINGSDIR
Var PARAMETERS
Var PARENTDIR
Var ROOTDIR
Var LASTDRIVE
Var LASTDIR
Var LANGID
Var TEMPDIR
Var ARCHITECTURE
Var COMPUTERID
Var PROGRAMSWITCH

!ifdef CUSTOMUI | NOUI
!ifdef CUSTOMUI
	!macro DetailPrintCustomUI TEXT
		ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "Silent"
		StrCmp $0 "true" +5
			SetDetailsPrint "textonly"
			DetailPrint "${TEXT}"
			Sleep 150
			SetDetailsPrint "listonly"
	!macroend
!else
	!macro DetailPrintCustomUI TEXT
	!macroend	
!endif
!define DetailPrintCustomUI "!insertmacro DetailPrintCustomUI"
!endif

!ifdef CUSTOMUI | NOUI
	Section HideWindow
		SetDetailsPrint "textonly"
		DetailPrint ""
		SetDetailsPrint "listonly"
		!ifdef NOUI
			HideWindow
		!endif
		!ifdef CUSTOMUI
			ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "Silent"
			StrCmp $0 "" "" +2
				WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "Silent" "false"
			StrCmp $0 "true" "" +2
				HideWindow
		!endif
	SectionEnd
!endif

Function DefaultVar
	; === Set Program Directory ===
	StrCpy $PROGRAMDIR "$EXEDIR\App\${APPDIR}"

	; === Set Program Directory (x64) ===
	!ifdef APPDIR64
		StrCpy $PROGRAMDIR64 "$EXEDIR\App\${APPDIR64}"
	!endif

	; === Set Program Executable ===
	StrCpy $PROGRAMEXE "${APPEXE}"

	; === Set Program Executable (x64) ===
	!ifdef APPEXE64
		StrCpy $PROGRAMEXE64 "${APPEXE64}"
	!endif

	; === Set Default Data ===
	StrCpy $DEFAULTDATA "$EXEDIR\App\DefaultData\${APPDIR}"

	; === Set Settings Directory ===
	StrCpy $SETTINGSDIR "$EXEDIR\Data\${APPDIR}"

	; === Get any passed parameters and set Parameters ===
	${GetParameters} $PARAMETERS

	; === Get and set Parent Directory ===
	${GetParent} "$EXEDIR" $PARENTDIR

	; === Get root directory and set Root Directory and Last Drive ===
	${GetRoot} "$EXEDIR" $ROOTDIR
	ReadINIStr $LASTDRIVE "$EXEDIR\Data\${APP}Portable.ini" "${APP}Portable" "LastDrive"

	; === Set Last Directory ===
	ReadINIStr $LASTDIR "$EXEDIR\Data\${APP}Portable.ini" "${APP}Portable" "LastDirectory"

	; === Set User Default Lang ===
	System::Call `kernel32::GetUserDefaultLangID() i .r0`
	StrCpy $LANGID $0

	; === Set Portable App Temp ===
	StrCpy $TEMPDIR "$TEMP\${APP}PortableTemp"

	; === Set Architecture ===
	System::Call `kernel32::GetCurrentProcess()i.s`
	System::Call `kernel32::IsWow64Process(is,*i.s)`
	Pop $0
	StrCmp $0 "0" "" +2
		StrCpy $ARCHITECTURE "x86"
	StrCmp $0 "1" "" +2
		StrCpy $ARCHITECTURE "x64"

	; === Set Computer ID ===
	${GetRoot} "$WINDIR" $0
	System::Call `kernel32::GetVolumeInformation(t,t,i,*i,*i,*i,t,i) i("$0\",,${NSIS_MAX_STRLEN},.r1,,,,${NSIS_MAX_STRLEN})` ; get computer id
	StrCpy $COMPUTERID $1

	; === Set Program Switch ===
	!ifdef APPSWITCH
		StrCpy $PROGRAMSWITCH `${APPSWITCH}`
	!else
		StrCpy $PROGRAMSWITCH ""
	!endif
FunctionEnd

Function CheckStart
	; === Check program executable ===
	!ifndef CUSTOMCHECKPROGRAMEXE
		IfFileExists "$PROGRAMDIR\$PROGRAMEXE" FoundProgramEXE NoProgramEXE
		NoProgramEXE:
			!ifdef CUSTOMUI
				HideWindow
			!endif
			${System::MessageBox} "${MB_OK}|${MB_ICONSTOP}" "Program executable not found | PerkedleApps" "Could not find $PROGRAMEXE in $PROGRAMDIR." $0
			!ifdef CUSTOMUI | NOUI
				Quit
			!else
				Abort
			!endif
		FoundProgramEXE:
	!else
		Call CheckProgramEXE
	!endif

	; === Check if launcher or app is running ===
	!ifndef CUSTOMCHECKRUNEXE
		ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "AllowMultipleInstances"
		StrCmp $0 "" "" +2
			WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "AllowMultipleInstances" "false"
		!ifdef NSIS_UNICODE
			System::Call `kernel32::CreateMutexW(i 0, i 0, t "$(^Name)") i .r1 ?e` ; check if launcher is already running
		!else
			System::Call `kernel32::CreateMutexA(i 0, i 0, t "$(^Name)") i .r1 ?e` ; check if launcher is already running
		!endif
		Pop $1
		StrCmp $1 "0" LauncherNotRunning LauncherAlreadyRunning
		LauncherAlreadyRunning:
			StrCmp $0 "true" RunAppAgain ShowMessageLauncherAlreadyRunning
			ShowMessageLauncherAlreadyRunning:
				FindWindow $0 "" "App is running | PerkedleApps"
				System::Call `user32::GetWindowText(i r0, t .r1, i r0) i.`
				StrCmp $1 "App is running | PerkedleApps" AppAlreadyRunning
					!ifdef CUSTOMUI
						HideWindow
					!endif
					${System::MessageBox} "${MB_OK}|${MB_ICONINFORMATION}" "Launcher already running | PerkedleApps" "${APPNAME} Portable is already running." $0
					!ifdef CUSTOMUI | NOUI
						Quit
					!else
						Abort
					!endif
			RunAppAgain:
				FindWindow $0 "" "App is running | PerkedleApps"
				System::Call `user32::GetWindowText(i r0, t .r1, i r0) i.`
				StrCmp $1 "App is running | PerkedleApps" AppAlreadyRunning
					FindProcDLL::FindProc "$PROGRAMEXE"
					StrCmp $R0 "1" "" CheckRunEXEEnd
						SetOutPath "$PROGRAMDIR"
						ClearErrors
						ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "ExecAsAdmin"
						IfErrors +5
						StrCmp $0 "" +4
						StrCmp $0 "true" +3
							StdUtils::ExecShellAsUser /NOUNLOAD `$PROGRAMSWITCH $PARAMETERS` "" "$PROGRAMDIR\$PROGRAMEXE"
							Goto +2
						Exec `"$PROGRAMDIR\$PROGRAMEXE"$PROGRAMSWITCH $PARAMETERS`
						!ifdef CUSTOMUI | NOUI
							Quit
						!else
							Abort
						!endif
		LauncherNotRunning:
			FindProcDLL::FindProc "$PROGRAMEXE"
			StrCmp $R0 "1" AppAlreadyRunning CheckRunEXEEnd
			AppAlreadyRunning:
				!ifdef CUSTOMUI
					HideWindow
				!endif
				${System::MessageBox} "${MB_OK}|${MB_ICONINFORMATION}" "App is running | PerkedleApps" "Another instances of ${APPNAME} is already running.$\nPlease close other instances of ${APPNAME} before running ${APPNAME} Portable." $0
				!ifdef CUSTOMUI | NOUI
					Quit
				!else
					Abort
				!endif
		CheckRunEXEEnd:
	!else
		Call CheckRunEXE
	!endif

	; === Check good or bad exit ===
	ReadINIStr $0 "$EXEDIR\Data\${APP}PortableRuntimeData.ini" "${APP}Portable" "Status"
	StrCmp $0 "running" "" CheckGoodOrBadExitEnd
		!ifdef CUSTOMUI
			HideWindow
		!endif
		${System::MessageBox} "${MB_OKCANCEL}|${MB_ICONEXCLAMATION}" "Bad exit | PerkedleApps" "Last exit of ${APPNAME} Portable did not restore settings.$\nWould you try to restore local and backup portable settings now?" $0
		StrCmp $0 "1" "" CheckGoodOrBadExitEnd ; if user click OK
			ReadINIStr $0 "$EXEDIR\Data\${APP}PortableRuntimeData.ini" "${APP}Portable" "PluginsDir"
				RMDir "/r" "$0"
			Call Close
	CheckGoodOrBadExitEnd:
FunctionEnd

Var RUNTIMEDATA
Function RuntimeData
	CreateDirectory "$EXEDIR\Data"
		WriteINIStr "$EXEDIR\Data\${APP}Portable.ini" "${APP}Portable" "LastDrive" "$ROOTDIR" ; store current drive letter
		WriteINIStr "$EXEDIR\Data\${APP}Portable.ini" "${APP}Portable" "LastDirectory" "$EXEDIR" ; store current directory
	SetFileAttributes "$EXEDIR\Data\${APP}Portable.ini" HIDDEN
		WriteINIStr "$EXEDIR\Data\${APP}PortableRuntimeData.ini" "${APP}Portable" "PluginsDir" "$PLUGINSDIR" ; store plugins dir
		WriteINIStr "$EXEDIR\Data\${APP}PortableRuntimeData.ini" "${APP}Portable" "Status" "running" ; store status
	FileOpen $RUNTIMEDATA "$EXEDIR\Data\${APP}PortableRuntimeData.ini" r ; lock file!
FunctionEnd

Function SplashScreen
	!ifdef CUSTOMUI
		${DetailPrintCustomUI} "Launch app"
		HideWindow
	!endif
	ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "DisableSplashScreen"
	StrCmp $0 "" "" +2
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "DisableSplashScreen" "false"
	ClearErrors
	ReadINIStr $1 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "SplashScreenName"
	IfErrors "" +2
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "SplashScreenName" ""
	StrCmp $0 "true" SplashScreenEnd ; skip splash screen
	StrCmp $1 "" ShowDefaultSplashScreen CustomSplashScreen
	ShowDefaultSplashScreen:
		InitPluginsDir
		File "/oname=$PLUGINSDIR\PerkedleApps" "Include\perkedleappssplash.bmp"
		!ifdef CUSTOMUI | NOUI
			newadvsplash::show /NOUNLOAD 1000 300 200 0xFF00FF "$PLUGINSDIR\PerkedleApps"
		!else
			newadvsplash::show /NOUNLOAD 1000 300 200 0xFF00FF /L "$PLUGINSDIR\PerkedleApps"
		!endif
		Delete "$PLUGINSDIR\PerkedleApps"
		Goto SplashScreenEnd
	CustomSplashScreen:
		IfFileExists "$EXEDIR\Data\$1.bmp" ShowCustomSplashScreen ShowDefaultSplashScreen
		ShowCustomSplashScreen:
			!ifdef CUSTOMUI | NOUI
				newadvsplash::show /NOUNLOAD 1000 300 200 0xFF00FF "$EXEDIR\Data\$1.bmp"
			!else
				newadvsplash::show /NOUNLOAD 1000 300 200 0xFF00FF /L "$EXEDIR\Data\$1.bmp"
			!endif
	SplashScreenEnd:
		!ifdef CUSTOMUI | NOUI
			newadvsplash::stop
		!endif
FunctionEnd
