; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define PublishPath "F:\source\setup-packages\database\sql"
#define DeploymentPath "F:\source\setup-packages\database"
#define MyAppName "ProcessDirector Database"
#define MyAppVersion "2015" ; Should be changed to match appropriate version number
#define MyAppPublisher "Greenfield Investments"

[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.)
AppId={{EE79180B-0C92-4E01-A72A-F8DDD3B93729}
AppName={#MyAppName}
;AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName={autopf}\{#MyAppPublisher}\{#MyAppName}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only).
;PrivilegesRequired=lowest
OutputDir={#DeploymentPath}
OutputBaseFilename={#MyAppName}_{#MyAppVersion}_Setup
SolidCompression=yes
WizardStyle=modern
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
Uninstallable=no

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "{#AddBackslash(PublishPath)}*.sql"; Flags: dontcopy

[Run]
Filename: "sqlcmd"; Parameters: "-S ""{code:GetSelectedSQLServerInstanceName}"" -i ""{tmp}\ProcessDirector.sql"" -o ""{app}\INSTALL_DATABASE.txt"""; BeforeInstall: ExtractTemporaryFile('ProcessDirector.sql'); Flags: runascurrentuser runhidden waituntilterminated; StatusMsg: "Executing database install script..."
Filename: "sqlcmd"; Parameters: "-S ""{code:GetSelectedSQLServerInstanceName}"" -Q ""{code:GetCreateLoginString}"" -o ""{app}\CREATE_PDADMIN_LOGIN.txt"""; Flags: runascurrentuser runhidden waituntilterminated; StatusMsg: "Creating PDAdmin login..."
Filename: "sqlcmd"; Parameters: "-S ""{code:GetSelectedSQLServerInstanceName}"" -d ""ProcessDirector"" -i ""{tmp}\PDAdmin.sql"" -o ""{app}\CREATE_PDADMIN_USER.txt"""; BeforeInstall: ExtractTemporaryFile('PDAdmin.sql'); Flags: runascurrentuser runhidden waituntilterminated; StatusMsg: "Creating PDAdmin user..."
Filename: "sqlcmd"; Parameters: "-S ""{code:GetSelectedSQLServerInstanceName}"" -d ""ProcessDirector"" -i ""{tmp}\RoleMemberships.sql"" -o ""{app}\ASSIGN_PDADMIN_ROLES.txt"""; BeforeInstall: ExtractTemporaryFile('RoleMemberships.sql'); Flags: runascurrentuser runhidden waituntilterminated; StatusMsg: "Assigning PDAdmin user role memberships..."

[Code]
var
  SQLServerConfigurationPage: TInputQueryWizardPage;
  Instances: TStringList;
  InstanceNameComboBox: TNewComboBox;

// Function retrieves a list of SQL Server 2022 instances
function GetSQL2022Instances(): TStringList;
var
  InstanceNamesPath: String;
  Names: TArrayOfString;
  i: Integer;
  Temp: String;
begin
  Result := TStringList.Create;
  
  InstanceNamesPath := 'SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL';
  
  // Get all value names in key
  if RegGetValueNames(HKLM64, InstanceNamesPath, Names) or
     RegGetValueNames(HKLM32, InstanceNamesPath, Names) then
  begin
    for i := 0 to GetArrayLength(Names) - 1 do
    begin
      if RegQueryStringValue(HKLM64, InstanceNamesPath, Names[i], Temp) or
         RegQueryStringValue(HKLM32, InstanceNamesPath, Names[i], Temp) then
      begin
        if Pos('MSSQL16.', Temp) = 1 then
        begin
          Result.Add(Names[i]);
        end;
      end;
    end;
  end;
end;
  
// Initialize the custom input page
procedure InitializeWizard();
var
  InstanceNameLabel: TLabel;
  i: Integer;
  index: Integer;
begin
  // Check for SQL Server 2022 instances
  Instances := GetSQL2022Instances();
  if Instances.Count = 0 then
  begin
    MsgBox('Setup did not find any SQL Server 2022 instances.' + #13#10 + 
           'Please install a SQL Server 2022 instance on this server before continuining with {#MyAppName} installation.',
           mbError,
           MB_OK);
    Abort;
  end;

  // Custom page for SQL Server configuration
  SQLServerConfigurationPage := CreateInputQueryPage(wpSelectDir,
    'SQL Server Configuration',
    'Configure the details of your Process Director database installation.',
    'Please specify a password for the PDAdmin login (uses SQL Server Authentication), and select the SQL Server 2022 instance to install to.');
  SQLServerConfigurationPage.Add('PDAdmin Password:', True);
  SQLServerConfigurationPage.Values[0] := '';
  InstanceNameLabel := TLabel.Create(WizardForm);
  InstanceNameLabel.Parent := SQLServerConfigurationPage.Surface;
  InstanceNameLabel.Left := SQLServerConfigurationPage.Edits[0].Left;
  InstanceNameLabel.Top := SQLServerConfigurationPage.Edits[0].Top + SQLServerConfigurationPage.Edits[0].Height + 16;
  InstanceNameLabel.Caption := 'SQL Server 2022 Instance:';
  InstanceNameComboBox := TNewComboBox.Create(WizardForm);
  InstanceNameComboBox.Parent := SQLServerConfigurationPage.Surface;
  InstanceNameComboBox.Style := csDropDownList;
  InstanceNameComboBox.Left := InstanceNameLabel.Left;
  InstanceNameComboBox.Top := InstanceNameLabel.Top + InstanceNameLabel.Height + 4;
  InstanceNameComboBox.Width := SQLServerConfigurationPage.Edits[0].Width;
  for i := 0 to Instances.Count - 1 do
  begin
    if Instances[i] = 'MSSQLSERVER' then
      InstanceNameComboBox.Items.Add(GetComputerNameString())
    else
      InstanceNameComboBox.Items.Add(GetComputerNameString() + '\' + Instances[i]);
  end;
  if Instances.Find('MSSQLSERVER', index) then
    InstanceNameComboBox.ItemIndex := index
  else
    InstanceNameComboBox.ItemIndex := 0;
  
  // Disable the instances combo box by default to allow installation only to default SQL Server instance
  // Setup executable launched with /EnableInstanceSelect=true enables combo box, but the installation will likely fail if a non-default instance is selected
  if ExpandConstant('{param:EnableInstanceSelect|false}') = 'false' then
    InstanceNameComboBox.Enabled := False;
end;

// Retrieves the selected SQL Server 2022 instance name for installation
// Includes computer name, returns only computer name for default if selected
function GetSelectedSQLServerInstanceName(Param: String): String;
begin
  Result := InstanceNameComboBox.Items[InstanceNameComboBox.ItemIndex];
end;

// Assembles and retrieves the "CREATE LOGIN" SQL command used in sqlcmd to create the PDAdmin login
function GetCreateLoginString(Param: String): String;
begin
  Result := 'CREATE LOGIN [PDAdmin] WITH PASSWORD=N''' + SQLServerConfigurationPage.Values[0] + ''', DEFAULT_DATABASE=[ProcessDirector], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF; ALTER SERVER ROLE [sysadmin] ADD MEMBER [PDAdmin];';
end;

// Validate user input
function NextButtonClick(CurPageID: Integer): Boolean;
var
  Response: Integer;
begin
  Result := True;
  
  if CurPageID = SQLServerConfigurationPage.ID then
  begin
    // Validate that required fields are not empty
    if Trim(SQLServerConfigurationPage.Values[0]) = '' then
    begin
      MsgBox('Please enter a value for: PDAdmin Password.', mbError, MB_OK);
      Result := False;
      Exit;
    end;
    
    // Prompt user to test connection before proceeding
    Response := MsgBox('Have you written down the chosen password?' + #13#10#13#10 +
                       'It is recommended to store the chosen password in a secure place before proceeding with installation.' + #13#10 +
                       'Click "Yes" to proceed, or "No" to go back.',
                       mbConfirmation, MB_YESNO);
    
    Result := (Response = IDYES);
  end;
end;