; JT2Go Installer with Prerequisite Checks
; Checks and installs VC++ Redistributables (x86/x64) and .NET Framework 4.8
; Supports silent installation: /VERYSILENT /SUPPRESSMSGBOXES
; Version 1.1

[Setup]
AppId={{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
AppName=Siemens JT2Go
AppVersion=2512
AppPublisher=WJDT
AppPublisherURL=https://www.plm.automation.siemens.com
DefaultDirName={autopf}\Siemens\JT2Go
CreateAppDir=no
PrivilegesRequired=admin
OutputDir=.\Output
OutputBaseFilename=JT2Go_Installer_v2512
SolidCompression=yes
WizardStyle=modern
SetupIconFile=gea-logo.ico
WizardImageFile=patrick.bmp
WizardSmallImageFile=patrick-sm.bmp
DisableWelcomePage=no
DisableDirPage=yes
DisableProgramGroupPage=yes

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

[Messages]
WelcomeLabel2=This will install Siemens JT2Go 2512 on your computer.%n%nThe installer will automatically check for and install the following prerequisites if needed:%n%n  - Microsoft Visual C++ Redistributable (x86)%n  - Microsoft Visual C++ Redistributable (x64)%n  - Microsoft .NET Framework 4.8%n%nAdministrative privileges are required.

[Files]
; Include all prerequisite installers
Source: "VC_redist.x86.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall
Source: "VC_redist.x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall
Source: "NDP48-x86-x64-AllOS-ENU.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall
Source: "JT2GoSetup.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall

[Code]
var
  ProgressPage: TOutputProgressWizardPage;
  PrereqPage: TOutputMsgMemoWizardPage;
  VCx86Needed, VCx64Needed, DotNetNeeded: Boolean;
  PrereqSummary: String;
  RebootRequired: Boolean;

// ============================================
// Silent-aware message box wrapper
// ============================================

procedure ShowMessage(Msg: String; MsgType: TMsgBoxType);
begin
  if not WizardSilent then
    MsgBox(Msg, MsgType, MB_OK);
end;

// ============================================
// Registry Detection Functions
// ============================================

// Check if VC++ 2015-2022 x64 Redistributable is installed
function IsVCx64Installed: Boolean;
var
  Installed: Cardinal;
begin
  Result := False;
  // Check primary registry location for VC++ 2015-2022 x64
  if RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Installed', Installed) then
  begin
    Result := (Installed = 1);
  end;
  // Also check newer registry path
  if not Result then
  begin
    if RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X64', 'Installed', Installed) then
    begin
      Result := (Installed = 1);
    end;
  end;
end;

// Check if VC++ 2015-2022 x86 Redistributable is installed
function IsVCx86Installed: Boolean;
var
  Installed: Cardinal;
begin
  Result := False;
  // On 64-bit Windows, x86 registry is in Wow6432Node
  if IsWin64 then
  begin
    if RegQueryDWordValue(HKLM, 'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86', 'Installed', Installed) then
    begin
      Result := (Installed = 1);
    end;
    if not Result then
    begin
      if RegQueryDWordValue(HKLM, 'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\X86', 'Installed', Installed) then
      begin
        Result := (Installed = 1);
      end;
    end;
  end
  else
  begin
    // On 32-bit Windows
    if RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86', 'Installed', Installed) then
    begin
      Result := (Installed = 1);
    end;
  end;
end;

// Check if .NET Framework 4.8 or later is installed
function IsDotNet48Installed: Boolean;
var
  Release: Cardinal;
begin
  Result := False;
  // .NET Framework 4.8 has release key >= 528040
  // 528040 = Windows 10 May 2019 Update
  // 528049 = All other Windows versions
  if RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', Release) then
  begin
    Result := (Release >= 528040);
  end;
end;

// ============================================
// Check Prerequisites (called early for silent mode)
// ============================================

procedure CheckPrerequisites;
begin
  VCx86Needed := not IsVCx86Installed;
  VCx64Needed := not IsVCx64Installed;
  DotNetNeeded := not IsDotNet48Installed;
  RebootRequired := False;
end;

// ============================================
// Wizard Page Setup
// ============================================

procedure InitializeWizard();
begin
  // Create progress page for prerequisite installation
  ProgressPage := CreateOutputProgressPage('Installing Prerequisites',
    'Please wait while the required components are being installed...');

  // Create prerequisites summary page (only shown in non-silent mode)
  PrereqPage := CreateOutputMsgMemoPage(wpWelcome,
    'Prerequisites Check',
    'The installer has checked for required components.',
    'Status of required prerequisites:',
    '');
end;

// ============================================
// Prerequisites Check on Welcome Page
// ============================================

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result := True;

  if CurPageID = wpWelcome then
  begin
    // Check all prerequisites
    CheckPrerequisites;

    // Build summary text
    PrereqSummary := '';

    PrereqSummary := PrereqSummary + 'Visual C++ Redistributable (x86): ';
    if VCx86Needed then
      PrereqSummary := PrereqSummary + 'NOT INSTALLED - Will be installed'#13#10
    else
      PrereqSummary := PrereqSummary + 'Already installed'#13#10;

    PrereqSummary := PrereqSummary + #13#10'Visual C++ Redistributable (x64): ';
    if VCx64Needed then
      PrereqSummary := PrereqSummary + 'NOT INSTALLED - Will be installed'#13#10
    else
      PrereqSummary := PrereqSummary + 'Already installed'#13#10;

    PrereqSummary := PrereqSummary + #13#10'.NET Framework 4.8: ';
    if DotNetNeeded then
      PrereqSummary := PrereqSummary + 'NOT INSTALLED - Will be installed'#13#10
    else
      PrereqSummary := PrereqSummary + 'Already installed'#13#10;

    PrereqSummary := PrereqSummary + #13#10'-------------------------------------------'#13#10;

    if VCx86Needed or VCx64Needed or DotNetNeeded then
      PrereqSummary := PrereqSummary + #13#10'Missing prerequisites will be installed before JT2Go.'#13#10 +
                       'This may require a system restart if .NET Framework 4.8 is installed.'
    else
      PrereqSummary := PrereqSummary + #13#10'All prerequisites are already installed.'#13#10 +
                       'JT2Go installation will proceed directly.';

    // Update the prereq page memo
    PrereqPage.RichEditViewer.RTFText := PrereqSummary;
  end;
end;

// ============================================
// Install Prerequisites Function
// ============================================

function InstallPrerequisites: Boolean;
var
  ResultCode: Integer;
  ErrorMsg: String;
begin
  Result := True;

  if not WizardSilent then
    ProgressPage.Show;

  try
    // ============================================
    // Install VC++ x86 if needed
    // ============================================
    if VCx86Needed then
    begin
      if not WizardSilent then
      begin
        ProgressPage.SetText('Installing Visual C++ Redistributable (x86)...',
                             'This may take a few moments...');
        ProgressPage.SetProgress(1, 4);
      end;

      // Run VC_redist.x86.exe with silent install
      // /install /quiet /norestart
      if not Exec(ExpandConstant('{tmp}\VC_redist.x86.exe'), '/install /quiet /norestart', '',
                  SW_HIDE, ewWaitUntilTerminated, ResultCode) then
      begin
        ErrorMsg := 'Failed to launch VC++ x86 installer.';
        ShowMessage(ErrorMsg, mbError);
        Result := False;
        Exit;
      end;

      // Check result code (0 = success, 3010 = success but reboot needed)
      if (ResultCode <> 0) and (ResultCode <> 3010) then
      begin
        ErrorMsg := 'VC++ x86 installation failed with error code: ' + IntToStr(ResultCode);
        ShowMessage(ErrorMsg, mbError);
        Result := False;
        Exit;
      end;

      if ResultCode = 3010 then
        RebootRequired := True;
    end;

    // ============================================
    // Install VC++ x64 if needed
    // ============================================
    if VCx64Needed then
    begin
      if not WizardSilent then
      begin
        ProgressPage.SetText('Installing Visual C++ Redistributable (x64)...',
                             'This may take a few moments...');
        ProgressPage.SetProgress(2, 4);
      end;

      if not Exec(ExpandConstant('{tmp}\VC_redist.x64.exe'), '/install /quiet /norestart', '',
                  SW_HIDE, ewWaitUntilTerminated, ResultCode) then
      begin
        ErrorMsg := 'Failed to launch VC++ x64 installer.';
        ShowMessage(ErrorMsg, mbError);
        Result := False;
        Exit;
      end;

      if (ResultCode <> 0) and (ResultCode <> 3010) then
      begin
        ErrorMsg := 'VC++ x64 installation failed with error code: ' + IntToStr(ResultCode);
        ShowMessage(ErrorMsg, mbError);
        Result := False;
        Exit;
      end;

      if ResultCode = 3010 then
        RebootRequired := True;
    end;

    // ============================================
    // Install .NET Framework 4.8 if needed
    // ============================================
    if DotNetNeeded then
    begin
      if not WizardSilent then
      begin
        ProgressPage.SetText('Installing .NET Framework 4.8...',
                             'This may take several minutes. Please wait...');
        ProgressPage.SetProgress(3, 4);
      end;

      // Run .NET installer with silent install
      // /q /norestart
      if not Exec(ExpandConstant('{tmp}\NDP48-x86-x64-AllOS-ENU.exe'), '/q /norestart', '',
                  SW_HIDE, ewWaitUntilTerminated, ResultCode) then
      begin
        ErrorMsg := 'Failed to launch .NET Framework 4.8 installer.';
        ShowMessage(ErrorMsg, mbError);
        Result := False;
        Exit;
      end;

      // Check result codes
      // 0 = success
      // 3010 = success, reboot required
      // 1641 = success, reboot initiated
      // 1602 = user cancelled
      // 1603 = fatal error
      // 5100 = computer does not meet requirements
      case ResultCode of
        0:
          begin
            // Success, no reboot needed
          end;
        3010, 1641:
          begin
            // Success but reboot required
            RebootRequired := True;
          end;
        1602:
          begin
            ErrorMsg := '.NET Framework installation was cancelled.';
            ShowMessage(ErrorMsg, mbError);
            Result := False;
            Exit;
          end;
        5100:
          begin
            ErrorMsg := 'This computer does not meet the requirements for .NET Framework 4.8.';
            ShowMessage(ErrorMsg, mbError);
            Result := False;
            Exit;
          end;
        else
          begin
            ErrorMsg := '.NET Framework 4.8 installation failed with error code: ' + IntToStr(ResultCode);
            ShowMessage(ErrorMsg, mbError);
            Result := False;
            Exit;
          end;
      end;
    end;

    if not WizardSilent then
      ProgressPage.SetProgress(4, 4);

  finally
    if not WizardSilent then
      ProgressPage.Hide;
  end;
end;

// ============================================
// Main Installation Step
// ============================================

procedure CurStepChanged(CurStep: TSetupStep);
var
  ResultCode: Integer;
  JT2GoExe: String;
  JT2GoParams: String;
  WorkDir: String;
  ShowWindow: Integer;
begin
  if CurStep = ssPostInstall then
  begin
    // For silent mode, check prerequisites here since wizard pages are skipped
    if WizardSilent then
      CheckPrerequisites;

    // First, install prerequisites if needed
    if VCx86Needed or VCx64Needed or DotNetNeeded then
    begin
      if not InstallPrerequisites then
      begin
        // Prerequisite installation failed
        Exit;
      end;
    end;

    // Check if reboot is required before continuing
    if RebootRequired then
    begin
      ShowMessage('.NET Framework 4.8 was installed successfully.' + #13#10 +
                  'A system restart is required to complete the installation.' + #13#10#13#10 +
                  'Please restart your computer and run this installer again to complete JT2Go installation.',
                  mbInformation);
      Exit;
    end;

    // Now run the JT2Go installer
    if not WizardSilent then
    begin
      ProgressPage.SetText('Installing JT2Go 2512...',
                           'The JT2Go installer will now launch. Please follow its prompts.');
      ProgressPage.SetProgress(1, 1);
      ProgressPage.Show;
    end;

    try
      JT2GoExe := ExpandConstant('{tmp}\JT2GoSetup.exe');
      WorkDir := ExpandConstant('{tmp}');

      // Determine parameters based on silent mode
      if WizardSilent then
      begin
        // Silent installation of JT2Go
        // /S = silent for exe wrapper, /qn = quiet no UI for MSI
        JT2GoParams := '/L1033 /S /v"/qn /norestart"';
        ShowWindow := SW_HIDE;
      end
      else
      begin
        // Interactive installation - just set language to English
        JT2GoParams := '/L1033';
        ShowWindow := SW_SHOW;
      end;

      // Execute JT2Go installer directly (not via batch file for better control)
      if not Exec(JT2GoExe, JT2GoParams, WorkDir, ShowWindow, ewWaitUntilTerminated, ResultCode) then
      begin
        ShowMessage('Failed to launch JT2Go installer.' + #13#10 +
                    'Please run JT2GoSetup.exe manually from the installation files.',
                    mbError);
        Exit;
      end;

      // Check result
      if ResultCode <> 0 then
      begin
        // Non-zero doesn't always mean failure for installers
        // 0 = success, 3010 = success with reboot required
        if ResultCode = 3010 then
        begin
          ShowMessage('Installation Complete!' + #13#10#13#10 +
                      'JT2Go 2512 has been installed successfully.' + #13#10 +
                      'A system restart may be required.',
                      mbInformation);
        end
        else
        begin
          ShowMessage('JT2Go installation completed with exit code: ' + IntToStr(ResultCode) + #13#10#13#10 +
                      'Please verify JT2Go is installed correctly.',
                      mbInformation);
        end;
      end
      else
      begin
        ShowMessage('Installation Complete!' + #13#10#13#10 +
                    'JT2Go 2512 has been installed successfully.' + #13#10#13#10 +
                    'All prerequisites were verified/installed:' + #13#10 +
                    '  - Visual C++ Redistributable (x86)' + #13#10 +
                    '  - Visual C++ Redistributable (x64)' + #13#10 +
                    '  - .NET Framework 4.8',
                    mbInformation);
      end;

    finally
      if not WizardSilent then
        ProgressPage.Hide;
    end;
  end;
end;

// ============================================
// Initialization - Admin Check
// ============================================

function InitializeSetup(): Boolean;
begin
  Result := True;
  RebootRequired := False;

  // Additional admin check at runtime
  // Note: PrivilegesRequired=admin already enforces this, but this provides a clearer message
  if not IsAdmin then
  begin
    ShowMessage('Administrator Privileges Required' + #13#10#13#10 +
                'This installer must be run with administrative privileges.' + #13#10#13#10 +
                'Please right-click the installer and select "Run as administrator".',
                mbError);
    Result := False;
    Exit;
  end;
end;

// ============================================
// Return proper exit code for reboot scenarios
// ============================================

function NeedRestart(): Boolean;
begin
  Result := RebootRequired;
end;
