; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "@PROJECT_TITLE@"
#define MyAppVersion "@PROJECT_VERSION@"
#define MyAppVersionText "@_VERSION@"
#define MyAppPublisher "Xaymars Technology Workshop"
#define MyAppURL "https://xaymar.com/"
#define MyAppCopyright "@PROJECT_COPYRIGHT@"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)

; Application Information
AppId={{DE56A03A-C8A4-474B-83B0-CFD270262D38}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
AppMutex={#MyAppName}

; Versioning
VersionInfoProductName={#MyAppName}
VersionInfoProductVersion={#MyAppVersion}
VersionInfoVersion={#MyAppVersion}
VersionInfoProductTextVersion={#MyAppVersionText}
VersionInfoTextVersion={#MyAppVersionText}
VersionInfoCompany={#MyAppPublisher}
VersionInfoCopyright={#MyAppCopyright}
VersionInfoDescription={#MyAppName} Setup

; Architecture (Platform is always Windows)
ArchitecturesInstallIn64BitMode=x64 arm64 ia64
ArchitecturesAllowed=@ARCH@

; Installation Modes
UsePreviousPrivileges=no
PrivilegesRequired=admin
PrivilegesRequiredOverridesAllowed=dialog commandline

; Wizard Information
WizardStyle=modern
WizardResizable=yes
SetupIconFile="@PROJECT_SOURCE_DIR@/media/icon.ico"
UninstallDisplayIcon={uninstallexe}

; Code Signing
;signtool=@ISS_CODESIGN_BIN_SHA1@
SignTool=signtool @ISS_CODESIGN_CMD_SHA1@ $f
SignTool=signtool @ISS_CODESIGN_CMD_SHA2@ $f
SignedUninstaller=yes

; Other Information
UsePreviousAppDir=no
Uninstallable=not IsPortablePagePortableChoiceChecked()
DefaultDirName={code:GetDefaultDirectory}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
LicenseFile="@ISS_SOURCE_DIR@/LICENSE"
OutputDir="@ISS_PACKAGE_DIR@"
OutputBaseFilename=@PACKAGE_NAME@-@_PACKAGE_SUFFIX_OVERRIDE@
Compression=lzma2/ultra64
SolidCompression=yes
LZMAAlgorithm=1

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "@ISS_FILES_DIR@/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "@PROJECT_SOURCE_DIR@/templates/msvc-redist-helper.exe"; DestDir: "{app}"; DestName: "msvc-redist-helper.exe"; Flags: ignoreversion dontcopy noencryption
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"

[Code]
// ------------------------------------------------------------------------------------------------------------------ //
var
  oPortablePageStaticChoice: TNewRadioButton;
  oPortablePagePortableChoice: TNewRadioButton;

function FindRegistryKey(): String; forward;
function GetDefaultDirectory(Value: String): String; forward;
function GetUninstallerPath(): String; forward;
function IsUpgrade(): Boolean; forward;
function IsPortablePagePortableChoiceChecked(): Boolean; forward;
function UninstallOldVersion(): Integer; forward;
procedure OnPortablePagePortableChoiceClick(Sender: TObject); forward;
procedure OnPortablePageStaticChoiceClick(Sender: TObject); forward;
function CreatePortablePage: TWizardPage; forward;
procedure InitializeWizard; forward;
function ShouldSkipPage(PageID: Integer): Boolean; forward;
function PrepareToInstall(var NeedsRestart: Boolean): String; forward;

// ------------------------------------------------------------------------------------------------------------------ //
function FindRegistryKey(): String;
begin
	Result := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting('AppId')}_is1');
end;

// ------------------------------------------------------------------------------------------------------------------ //
function GetDefaultDirectory(Value: String): String;
var
	sInstallPath: String;
begin
	// 1. Use the path we were given on call.
	sInstallPath := Value;

	// 2. If that was empty, try and find it ourselves from the registry.
	if (sInstallPath = '') then
		RegQueryStringValue(HKA64, FindRegistryKey(), 'InstallLocation', sInstallPath);

	// 2. If empty, try and find the "Local Machine" installation of OBS Studio.
	if (sInstallPath = '') then
		RegQueryStringValue(HKLM64, 'SOFTWARE\OBS Studio', '', sInstallPath);

	// 3. If empty, try and find the "Current User" installation of OBS Studio.
	if (sInstallPath = '') then
		RegQueryStringValue(HKCU64, 'SOFTWARE\OBS Studio', '', sInstallPath);

	// 6. If empty, just use the default path.
	if (sInstallPath = '') then
		sInstallPath := ExpandConstant('{commonpf}\obs-studio');

	Result := sInstallPath
end;

// ------------------------------------------------------------------------------------------------------------------ //
function GetUninstallerPath(): String;
var
	sRegistryKey: String;
	sUninstallerPath: String;
begin
	sRegistryKey := FindRegistryKey();

	RegQueryStringValue(HKLM64, sRegistryKey, 'UninstallString', sUninstallerPath);

	if (sUninstallerPath = '') then
		RegQueryStringValue(HKCU64, sRegistryKey, 'UninstallString', sUninstallerPath);

	if (sUninstallerPath = '') then
		RegQueryStringValue(HKLM32, sRegistryKey, 'UninstallString', sUninstallerPath);

	if (sUninstallerPath = '') then
		RegQueryStringValue(HKCU32, sRegistryKey, 'UninstallString', sUninstallerPath);

	Result := sUninstallerPath;
end;

// ------------------------------------------------------------------------------------------------------------------ //
function IsUpgrade(): Boolean;
begin
	Result := (not IsPortablePagePortableChoiceChecked()) and (GetUninstallerPath() <> '');
end;

// ------------------------------------------------------------------------------------------------------------------ //
function UninstallOldVersion(): Integer;
var
	sUninstallerPath: String;
	iResultCode: Integer;
begin
	Result := 0;
	sUninstallerPath := GetUninstallerPath();
	if (sUninstallerPath <> '') then begin
		sUninstallerPath := RemoveQuotes(sUninstallerPath);
		if Exec(sUninstallerPath, '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES', '', SW_HIDE, ewWaitUntilTerminated, iResultCode) then begin
			Result := iResultCode
		end else begin
			Result := 1
		end;
	end;
end;

// ------------------------------------------------------------------------------------------------------------------ //
procedure OnPortablePagePortableChoiceClick(Sender: TObject);
begin
  oPortablePageStaticChoice.Checked := False;
  oPortablePagePortableChoice.Checked := True;
end;

procedure OnPortablePageStaticChoiceClick(Sender: TObject);
begin
  if (not oPortablePageStaticChoice.Enabled) then begin
    OnPortablePagePortableChoiceClick(Sender);
  end else begin
    oPortablePageStaticChoice.Checked := True;
    oPortablePagePortableChoice.Checked := False;
  end;
end;

function IsPortablePagePortableChoiceChecked(): Boolean;
begin
	Result := oPortablePagePortableChoice.Checked;
end;

function CreatePortablePage: TWizardPage;
var
  oPage: TWizardPage;
  oStaticPanel: TPanel;
  oStaticChoice: TNewRadioButton;
  oStaticText: TLabel;
  oStaticWarningText: TLabel;
  oPortablePanel: TPanel;
  oPortableChoice: TNewRadioButton;
  oPortableText: TLabel;
begin
  // Build a page that asks a user if they want to use Movable or Static installation.
  oPage := CreateCustomPage(wpLicense,
    'Installation Type',
    'Select how to install StreamFX on your System');

  oStaticPanel := TPanel.Create(oPage);
  oStaticPanel.Parent := oPage.Surface;
  oStaticPanel.ParentBackground := False;
  oStaticPanel.Left := ScaleX(5);
  oStaticPanel.Top := ScaleY(5);
  oStaticPanel.Width := oPage.SurfaceWidth - ScaleX(10);
  oStaticPanel.Height := ScaleY(100);
  oStaticPanel.Anchors := [akLeft, akTop, akRight];
  oStaticPanel.Color := clWindow;
  oStaticPanel.BevelKind := bkTile;
  oStaticPanel.BevelInner := bvNone;
  oStaticPanel.BevelOuter := bvRaised;
  oStaticPanel.BevelWidth := 1;
  oStaticPanel.OnClick := @OnPortablePageStaticChoiceClick;

  oStaticChoice := TNewRadioButton.Create(oStaticPanel);
  oPortablePageStaticChoice := oStaticChoice;
  oStaticChoice.Parent := oStaticPanel;
  oStaticChoice.ParentBackground := False;
  oStaticChoice.Left := ScaleX(5);
  oStaticChoice.Top := ScaleY(5);
  oStaticChoice.Width := oStaticPanel.Width - ScaleX(10);
  oStaticChoice.Height := ScaleY(20);
  oStaticChoice.Anchors := [akLeft, akTop, akRight];
  oStaticChoice.Caption := 'Static';
  oStaticChoice.Font.Style := [fsBold];
  oStaticChoice.OnClick := @OnPortablePageStaticChoiceClick;

  oStaticText := TLabel.Create(oStaticPanel);
  oStaticText.Parent := oStaticPanel;
  oStaticText.AutoSize := False;
  oStaticText.Left := ScaleX(5);
  oStaticText.Top := ScaleY(5) + oStaticChoice.Top + oStaticChoice.Height;
  oStaticText.Width := oStaticPanel.Width - ScaleX(10);
  oStaticText.Height := oStaticPanel.Height - ScaleX(5) - oStaticText.Top;
  oStaticText.Anchors := [akLeft, akTop, akRight];
  oStaticText.WordWrap := True
  oStaticText.Caption := 'Install for use in a static version of OBS Studio, with all necessary features to support it.';
  oStaticText.OnClick := @OnPortablePageStaticChoiceClick;

  oPortablePanel := TPanel.Create(oPage);
  oPortablePanel.Parent := oPage.Surface;
  oPortablePanel.ParentBackground := False;
  oPortablePanel.Left := ScaleX(5);
  oPortablePanel.Top := ScaleY(5) + oStaticPanel.Top + oStaticPanel.Height;
  oPortablePanel.Width := oPage.SurfaceWidth - ScaleX(10);
  oPortablePanel.Height := ScaleY(100);
  oPortablePanel.Anchors := [akLeft, akTop, akRight];
  oPortablePanel.Color := clWindow;
  oPortablePanel.BevelKind := bkTile;
  oPortablePanel.BevelInner := bvNone;
  oPortablePanel.BevelOuter := bvRaised;
  oPortablePanel.BevelWidth := 1;
  oPortablePanel.OnClick := @OnPortablePagePortableChoiceClick;

  oPortableChoice := TNewRadioButton.Create(oPortablePanel);
  oPortablePagePortableChoice := oPortableChoice;
  oPortableChoice.Parent := oPortablePanel;
  oPortableChoice.ParentBackground := False;
  oPortableChoice.Left := ScaleX(5);
  oPortableChoice.Top := ScaleY(5);
  oPortableChoice.Width := oPortablePanel.Width - ScaleX(10);
  oPortableChoice.Height := ScaleY(20);
  oPortableChoice.Anchors := [akLeft, akTop, akRight];
  oPortableChoice.Caption := 'Portable';
  oPortableChoice.Font.Style := [fsBold];
  oPortableChoice.OnClick := @OnPortablePagePortableChoiceClick;

  oPortableText := TLabel.Create(oPortablePanel);
  oPortableText.Parent := oPortablePanel;
  oPortableText.AutoSize := False;
  oPortableText.Left := ScaleX(5);
  oPortableText.Top := ScaleY(5) + oPortableChoice.Top + oPortableChoice.Height;
  oPortableText.Width := oPortablePanel.Width - ScaleX(10);
  oPortableText.Height := oPortablePanel.Height - ScaleX(5) - oPortableText.Top;
  oPortableText.Anchors := [akLeft, akTop, akRight];
  oPortableText.WordWrap := True
  oPortableText.Caption := 'Install for use in portable or multi-environment scenarios, which require StreamFX to not be tied to the System itself. The uninstaller, automatic updates and other system-dependent features will be unavailable.';
  oPortableText.OnClick := @OnPortablePagePortableChoiceClick;

  if (not IsAdmin()) then begin
    oStaticWarningText := TLabel.Create(oStaticPanel);
    oStaticWarningText.Parent := oStaticPanel;
    oStaticWarningText.AutoSize := False;
    oStaticWarningText.Left := ScaleX(5);
    oStaticWarningText.Top := oPortablePanel.Height - ScaleY(5) - ScaleY(15);
    oStaticWarningText.Width := oPortablePanel.Width - ScaleX(10);
    oStaticWarningText.Height := ScaleY(15);
    oStaticWarningText.Anchors := [akLeft, akBottom, akRight];
    oStaticWarningText.WordWrap := True
    oStaticWarningText.Font.Color := clRed;
    oStaticWarningText.Font.Style := [fsBold];
    oStaticWarningText.Caption := 'Please launch the Installer as Administrator for static installations.';

    oStaticPanel.Enabled := False;
    oStaticChoice.Enabled := False;
    oStaticText.Enabled := False;

    oStaticChoice.Checked := False;
    oPortableChoice.Checked := True;
  end else begin
    oStaticChoice.Checked := True;
    oPortableChoice.Checked := False;
  end;

  Result := oPage;
end;

procedure InitializeWizard;
var
  oPortablePage: TWizardPage;
begin
  oPortablePage := CreatePortablePage();
end;

// ------------------------------------------------------------------------------------------------------------------ //
function ShouldSkipPage(PageID: Integer): Boolean;
begin
	Result := False;
	if (PageID = wpSelectDir) then begin
		if (not IsPortablePagePortableChoiceChecked()) then begin
			if (IsUpgrade()) then begin
				Result := True;
				Exit;
			end;
		end;
	end;
end;

// ------------------------------------------------------------------------------------------------------------------ //
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
	iResultCode: Integer;
begin
	// Attempt to remove old version if it exists.
	if (IsUpgrade()) then begin
		UninstallOldVersion();
	end;

	// Also ensure that we have the necessary prerequisites installed to run the program.
    ExtractTemporaryFile('msvc-redist-helper.exe');
    Exec(ExpandConstant('{tmp}\msvc-redist-helper.exe'), '2019', '', SW_HIDE, ewWaitUntilTerminated, iResultCode);
end;
