# set-executionpolicy unrestricted

# Check if running as administrator
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Host "This script requires administrator privileges. Attempting to restart as administrator..." -ForegroundColor Yellow
    
    # Get the current script path
    $scriptPath = $MyInvocation.MyCommand.Path
    
    # Restart the script with administrator privileges
    try {
        Start-Process PowerShell -Verb RunAs -ArgumentList "-ExecutionPolicy Bypass -File `"$scriptPath`""
        exit
    }
    catch {
        Write-Error "Failed to restart as administrator. Please run this script as administrator manually."
        Write-Host "Right-click on PowerShell and select 'Run as administrator', then run this script again." -ForegroundColor Red
        pause
        exit 1
    }
}

Write-Host "Running with administrator privileges." -ForegroundColor Green

$uid = $Env:UserName

# Get the directory where this script is located
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path

Copy-Item -Path "$scriptDir\FastStone" -Destination "C:\Users\$uid\AppData\Local\" -Recurse -Force

# Define the Firefox installation directory
$firefoxPath = "C:\Program Files\Mozilla Firefox"
$distributionPath = Join-Path -Path $firefoxPath -ChildPath "distribution"

# Ensure the distribution folder exists
if (-not (Test-Path -Path $distributionPath)) {
    New-Item -Path $distributionPath -ItemType Directory | Out-Null
}

# Define the source and destination paths for policies.json
$sourceFile = "$scriptDir\Firefox\policies.json"
$destinationFile = Join-Path -Path $distributionPath -ChildPath "policies.json"

# Copy/replace the policies.json file
Copy-Item -Path $sourceFile -Destination $destinationFile -Force

Write-Host "policies.json has been copied/replaced in the distribution folder."

$forgePath = "C:\ProgramData\miniforge3"
$forgeScriptsPath = "C:\ProgramData\miniforge3\Scripts"
$systemPathReference = [System.Environment]::GetEnvironmentVariable("Path", "Machine")

# Check if the path already contains $forgePath
if (-not ($systemPathReference -split ";" | Where-Object { $_ -eq $forgePath })) {
    # Append $forgePath to the existing path, with proper separation by semicolon
    $newPath = $systemPathReference + ";" + $forgePath
    [System.Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
}

# Check if the path already contains $forgeScriptsPath
if (-not ($systemPathReference -split ";" | Where-Object { $_ -eq $forgeScriptsPath })) {
    # Get the updated path (in case it was modified above)
    $currentPath = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
    # Append $forgeScriptsPath to the existing path, with proper separation by semicolon
    $newPath = $currentPath + ";" + $forgeScriptsPath
    [System.Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
}

# Define the base Firefox profiles directory
$profilesDir = "$env:APPDATA\Mozilla\Firefox\Profiles"

# Define the source user.js file
$sourceFile = "$scriptDir\Firefox\user.js"  # Use absolute path based on script location

# Check if the source file exists
if (-not (Test-Path -Path $sourceFile)) {
    Write-Error "Source user.js file not found at $sourceFile"
    exit
}

# Loop through all subdirectories in the profiles folder
Get-ChildItem -Path $profilesDir -Directory | ForEach-Object {
    $profilePath = $_.FullName
    $destinationFile = Join-Path -Path $profilePath -ChildPath "user.js"
    
    # Copy the user.js file to the profile directory
    Copy-Item -Path $sourceFile -Destination $destinationFile -Force
    Write-Host "user.js has been placed in: $profilePath"
}

Write-Host "Operation completed for all Firefox profiles."



# Path to the CSV file
$csvFilePath = "$scriptDir\registry.csv"
$entries = Import-Csv -Path $csvFilePath

foreach ($entry in $entries) {
    # Trim fields to remove extra spaces
    $registryPath = $entry.registryPath.Trim()
    $propertyName = $entry.propertyName.Trim()
    $propertyType = $entry.propertyType.Trim()
    $propertyValue = $entry.propertyValue.Trim()

    # Validate required fields
    if (-not $registryPath -or -not $propertyName -or -not $propertyType -or -not $propertyValue) {
        Write-Warning "Skipping row with incomplete data: $($entry | Out-String)"
        continue
    }

    # Print debug info
    #Write-Host "Processing: Path=$registryPath Name=$propertyName Type=$propertyType Value=$propertyValue"

    # Check if registry path exists, create if necessary
    if (-not (Test-Path $registryPath)) {
        try {
            New-Item -Path $registryPath -Force | Out-Null
            Write-Host "Created missing path: $registryPath"
        } catch {
            Write-Warning "Failed to create path: $registryPath. $_"
            continue
        }
    }

    # Set the registry property
    try {
        Set-ItemProperty -Path $registryPath -Name $propertyName -Type $propertyType -Value $propertyValue
        # Write-Host "Successfully set $propertyName in $registryPath to $propertyValue."
    } catch {
        Write-Warning "Failed to set $propertyName in $registryPath. $_"
    }
}

# Wallpaper and Lock Screen
Write-Host "Setting desktop wallpaper and lock screen..."

$wallpaperDest = "C:\Windows\Web\Wallpaper\Custom"
New-Item -Path $wallpaperDest -ItemType Directory -Force | Out-Null
Copy-Item -Path "$scriptDir\wallpaper\Wallpaper.png" -Destination "$wallpaperDest\Wallpaper.png" -Force
Copy-Item -Path "$scriptDir\wallpaper\Lockscreen.png" -Destination "$wallpaperDest\Lockscreen.png" -Force

Add-Type -TypeDefinition @"
using System.Runtime.InteropServices;
public class Wallpaper {
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
}
"@
[Wallpaper]::SystemParametersInfo(0x0014, 0, "$wallpaperDest\Wallpaper.png", 3) | Out-Null
Write-Host "Desktop wallpaper and lock screen configured."

# ShareX - Remove "Capture Entire Screen" shortcut
Write-Host "Configuring ShareX shortcuts..."

# Find ShareX settings directory in Documents folder
$shareXSettingsDir = "$env:USERPROFILE\Documents\ShareX"
$settingsFile = Join-Path -Path $shareXSettingsDir -ChildPath "HotkeysConfig.json"

if (Test-Path -Path $settingsFile) {
    try {
        # Load the current hotkeys configuration
        $hotkeysConfig = Get-Content -Path $settingsFile -Raw | ConvertFrom-Json

        # Find and modify the "Capture entire screen" hotkey to disable it
        foreach ($hotkey in $hotkeysConfig) {
            if ($hotkey.TaskSettings.Description -eq "Capture entire screen") {
                $hotkey.HotkeyInfo.IsActive = $false
                Write-Host "Disabled 'Capture entire screen' hotkey in ShareX"
            }
        }

        # Save the modified configuration back to file
        $hotkeysConfig | ConvertTo-Json -Depth 10 | Set-Content -Path $settingsFile
        Write-Host "ShareX hotkeys configuration updated successfully"
    } catch {
        Write-Warning "Failed to update ShareX hotkey configuration: $_"
    }
} else {
    Write-Warning "ShareX settings file not found at: $settingsFile"
}

# ShareX - Modify PrintScreen shortcuts
Write-Host "Configuring ShareX shortcuts..."

# Find ShareX settings directory in Documents folder
$shareXSettingsDir = "$env:USERPROFILE\Documents\ShareX"
$settingsFile = Join-Path -Path $shareXSettingsDir -ChildPath "HotkeysConfig.json"

if (Test-Path -Path $settingsFile) {
    try {
        # Load the current hotkeys configuration
        $hotkeysConfig = Get-Content -Path $settingsFile -Raw | ConvertFrom-Json

        # Find the Ctrl+PrintScreen entry (usually for rectangle region)
        $ctrlPrintscreenEntry = $hotkeysConfig.Hotkeys | Where-Object { $_.HotkeyInfo.Hotkey -eq "PrintScreen, Control" }
        if ($ctrlPrintscreenEntry) {
            $ctrlPrintscreenEntry.HotkeyInfo.Hotkey = "PrintScreen"
            Write-Host "Changed 'Ctrl+PrintScreen' to just 'PrintScreen'"
        }

        # Find the PrintScreen only entry (usually "Capture entire screen") and disable it
        $printscreenEntry = $hotkeysConfig.Hotkeys | Where-Object { $_.HotkeyInfo.Hotkey -eq "PrintScreen" -and $_ -ne $ctrlPrintscreenEntry }
        if ($printscreenEntry) {
            # Remove the entry from the array
            $newHotkeys = $hotkeysConfig.Hotkeys | Where-Object { $_ -ne $printscreenEntry }
            $hotkeysConfig.Hotkeys = $newHotkeys
            Write-Host "Removed entry with just PrintScreen shortcut"
        }

        # Save the modified configuration back to file
        $hotkeysConfig | ConvertTo-Json -Depth 10 | Set-Content -Path $settingsFile
        Write-Host "ShareX hotkeys configuration updated successfully"
    } catch {
        Write-Warning "Failed to update ShareX hotkey configuration: $_"
    }
} else {
    Write-Warning "ShareX settings file not found at: $settingsFile"
}

# ShareX - Replace configuration files and remove backup folder
Write-Host "Configuring ShareX..."

# Define the source and destination paths
$shareXSourceDir = ".\ShareX"
$shareXDestDir = "$env:USERPROFILE\Documents\ShareX"
$backupDir = Join-Path -Path $shareXDestDir -ChildPath "Backup"
$shareXExePath = "C:\Program Files\ShareX\ShareX.exe"

# Close ShareX if it's running
$shareXProcess = Get-Process -Name "ShareX" -ErrorAction SilentlyContinue
if ($shareXProcess) {
    Write-Host "Closing ShareX process..."
    $shareXProcess | Stop-Process -Force
    Start-Sleep -Seconds 1  # Give it a moment to close
}

# Check if the source directory exists
if (-not (Test-Path -Path $shareXSourceDir)) {
    Write-Warning "ShareX source directory not found at: $shareXSourceDir"
} else {
    # Ensure the destination directory exists
    if (-not (Test-Path -Path $shareXDestDir)) {
        New-Item -Path $shareXDestDir -ItemType Directory -Force | Out-Null
        Write-Host "Created ShareX directory at: $shareXDestDir"
    }

    # Delete Backup folder first if it exists
    if (Test-Path -Path $backupDir) {
        try {
            Remove-Item -Path $backupDir -Recurse -Force
            Write-Host "Removed ShareX Backup folder"
        } catch {
            Write-Warning "Failed to remove ShareX Backup folder: $_"
        }
    }

    # Copy ApplicationConfig.json
    $sourceAppConfig = Join-Path -Path $shareXSourceDir -ChildPath "ApplicationConfig.json"
    $destAppConfig = Join-Path -Path $shareXDestDir -ChildPath "ApplicationConfig.json"
    if (Test-Path -Path $sourceAppConfig) {
        Copy-Item -Path $sourceAppConfig -Destination $destAppConfig -Force
        Write-Host "Copied ApplicationConfig.json to $shareXDestDir"
    } else {
        Write-Warning "ApplicationConfig.json not found in source directory"
    }

    # Copy HotkeysConfig.json
    $sourceHotkeysConfig = Join-Path -Path $shareXSourceDir -ChildPath "HotkeysConfig.json"
    $destHotkeysConfig = Join-Path -Path $shareXDestDir -ChildPath "HotkeysConfig.json"
    if (Test-Path -Path $sourceHotkeysConfig) {
        Copy-Item -Path $sourceHotkeysConfig -Destination $destHotkeysConfig -Force
        Write-Host "Copied HotkeysConfig.json to $shareXDestDir"
    } else {
        Write-Warning "HotkeysConfig.json not found in source directory"
    }
}

# Restart ShareX if it was running
if ($shareXProcess -and (Test-Path -Path $shareXExePath)) {
    Write-Host "Restarting ShareX with silent flag..."
    Start-Process -FilePath $shareXExePath -ArgumentList "-s"
} elseif ($shareXProcess) {
    Write-Warning "Could not restart ShareX: Executable not found at $shareXExePath"
}

# XMouseButtonControl - Replace configuration files
Write-Host "Configuring XMouseButtonControl..."

# Define the source and destination paths
$xmbcSourceDir = ".\XMouseButtonControl"
$xmbcDestDir = "$env:APPDATA\Highresolution Enterprises\XMouseButtonControl"

# Ensure the destination directory exists
if (-not (Test-Path -Path $xmbcDestDir)) {
    New-Item -Path $xmbcDestDir -ItemType Directory -Force | Out-Null
    Write-Host "Created XMouseButtonControl directory at: $xmbcDestDir"
}

# Copy XMBCSettings.xml
$sourceSettings = Join-Path -Path $xmbcSourceDir -ChildPath "XMBCSettings.xml"
$destSettings = Join-Path -Path $xmbcDestDir -ChildPath "XMBCSettings.xml"
if (Test-Path -Path $sourceSettings) {
    Copy-Item -Path $sourceSettings -Destination $destSettings -Force
    Write-Host "Copied XMBCSettings.xml to $xmbcDestDir"
} else {
    Write-Warning "XMBCSettings.xml not found in source directory"
}

# Copy profile file
$sourceProfile = Join-Path -Path $xmbcSourceDir -ChildPath "psymon's XMBC Settings.xmbcp"
$destProfile = Join-Path -Path $xmbcDestDir -ChildPath "psymon's XMBC Settings.xmbcp"
if (Test-Path -Path $sourceProfile) {
    Copy-Item -Path $sourceProfile -Destination $destProfile -Force
    Write-Host "Copied 'psymon's XMBC Settings.xmbcp' to $xmbcDestDir"
} else {
    Write-Warning "psymon's XMBC Settings.xmbcp not found in source directory"
}

# Update Windows hosts file with entries to block license servers
Write-Host "Updating Windows hosts file..."

# Define the hosts file path
$hostsFile = "$env:SystemRoot\System32\drivers\etc\hosts"

# Define the input file path (relative to script location)
$hostsInputFile = "$scriptDir\hosts.txt"

# Check if the input file exists
if (-not (Test-Path -Path $hostsInputFile)) {
    Write-Warning "hosts.txt file not found at $hostsInputFile"
} else {
    try {
        # Read the current hosts file
        $hostsContent = Get-Content -Path $hostsFile -ErrorAction Stop
        
        # Read the hostnames to block from the input file
        $hostnamesToBlock = Get-Content -Path $hostsInputFile | 
            Where-Object { $_ -and $_.Trim() -ne "" -and -not $_.Trim().StartsWith("#") } |
            ForEach-Object { $_.Trim() }
        
        # Create a backup of the original hosts file
        $backupFile = "$hostsFile.backup.$(Get-Date -Format 'yyyyMMdd-HHmmss')"
        Copy-Item -Path $hostsFile -Destination $backupFile -Force
        Write-Host "Created backup: $backupFile"
        
        # Track if any changes were made
        $changesMade = $false
        
        # Check each hostname and add if not already present
        foreach ($hostname in $hostnamesToBlock) {
            # Check if this hostname is already in the hosts file (case-insensitive)
            $existingEntry = $hostsContent | Where-Object { 
                $_ -match "^\s*127\.0\.0\.1\s+$([regex]::Escape($hostname))\s*$" -or
                $_ -match "^\s*127\.0\.0\.1\s+.*\b$([regex]::Escape($hostname))\b"
            }
            
            if (-not $existingEntry) {
                # Add the entry
                $hostsContent += "127.0.0.1 $hostname"
                Write-Host "Added: $hostname"
                $changesMade = $true
            } else {
                Write-Host "Already exists: $hostname" -ForegroundColor DarkGray
            }
        }
        
        # Write the updated hosts file if changes were made
        if ($changesMade) {
            $hostsContent | Set-Content -Path $hostsFile -Encoding ASCII -Force
            Write-Host "Hosts file updated successfully with $($hostnamesToBlock.Count) entries processed"
        } else {
            Write-Host "No changes needed - all entries already exist in hosts file"
        }
        
        # Flush DNS cache to apply changes immediately
        Write-Host "Flushing DNS cache..."
        & ipconfig /flushdns | Out-Null
        Write-Host "DNS cache flushed"
        
    } catch {
        Write-Error "Failed to update hosts file: $_"
        Write-Host "Make sure the script is running with administrator privileges" -ForegroundColor Red
    }
}
