<# calling the wslMount function will attach one or more physical disks to a wsl instance
	-drives
		This parameter specifies which disks, and is an array of what Windows calls the Friendly Name.
		You can see these by calling `Get-PhysicalDisk`.
	-count
		The list of friendly names are not necessarily unique (eg if you have multiple of the same model of drive).
		Count is required so that you know how many disks have been matched, and will be passed to WSL.
	-wsl
		The name of the wsl install you want to interact with, defaults to the default wsl instance.
	-mount
		The path to which the disks will be mounted, the directory cannot already exist, but its parent must.
		Non-absolute paths are relative to /mnt/wsl, and it is recommended to use a single folder name here, as
		this is the only place where mounts will appear to the windows environment (via '\\wsl.localhost').
		In the case you have provided -mapper, you may omit this, and it is just copied from that value.
	-mapper
		Specifies that the disks individually use luks 2 encryption prior to mounting.
		The string passed here is used to name the mapper device.
	-options
		An array of strings that will be used as the -o for linux' `mount`
	-format
		A linux command to which the disk device paths are appended that should format the disks.
		Eg `-format 'mkfs.btrfs -f'` may result in the command `mkfs.btrfs -f /dev/sdd /dev/sde /dev/sdf` being ran in wsl

Example:
#encrypt four disks, format them using btrfs, and raid them together, mounting at \\wsl$\Debian\mnt\wsl\data
wslMount `
	-drives  'WDC WD20 EARS-00S8B1','ST2000DL 003-9VT166','ST2000DM 006-2DM164' `
	-mapper  'data' `
	-count   4 `
	-format 'mkfs.btrfs -m raid1 -d raid0 -f'
#subsequent mounts omit the -format option, and we can decide to use some btrfs-specific mount options
wslMount `
	-drives  'WDC WD20 EARS-00S8B1','ST2000DL 003-9VT166','ST2000DM 006-2DM164' `
	-mapper  'data' `
	-count   4 `
	-options space_cache,compress

Read all outputs.
If you see an error, Ctrl+C at the next prompt, and fix the issue (and/or cleanup).
If it's something like a mistyped decryption key too many times letting it continue (failing to mount) will be fine, and actually perform cleanup for you (it'll fail to unmount, but will detach the disks from wsl for you).
But if formatting disks for the first time from something like say, NTFS, and an error said it was unable to attach one of the disks, definitely exit out (and in this case detach any disks from wsl and remove drive letters from windows mounted volumes).
#>


Function GetDisks { Param($matcher)
	Get-PhysicalDisk `
	| ?{ $_.FriendlyName -match "^$matcher`$" } `
	| Sort-Object -Property SerialNumber `
	| %{'\\.\PHYSICALDRIVE' + $_.DeviceId}
}

Function GetDevices { Param($wsl, $matcher)
	"lsblk -o PATH,VENDOR,MODEL | grep -oP '^\S+(?=\s+$matcher\s*`$)' | sort" `
	| %{
		wsl `
			--distribution $wsl `
			-- bash -c $_
	}
}

Function AttachDisks { Param($disks, $wsl)
	#The mount command must be ran as your user, not admin.
	#I have no idea how, but if you run the script as admin, you cannot see the mount, even if you log into wsl.
	#Only the admin at that point can see the mount when they log into wsl, even if the same user!
	#Thus only this portion should be elevated.
	#
	#Start-Process really fucks with stuff passed into argumentlist
	#and the below hack was really the only way to do it.
	Start-Process `
		-Verb RunAs `
		-Wait `
		-FilePath powershell `
		-ArgumentList `
@"
	($(
		($disks | %{ "'$_'" }) -join ','
	)) | %{
		'Attaching',`$_ -join ' '
		wsl --distribution $wsl --mount `$_ --bare
	}
	pause
"@
}

Function ToMatcher { Param($names)
	#[regex]::Escape() turns ' ' into '\ ' for some ungodly reason
	"($((
		$names `
		| %{ <#[regex]::Escape#>($_) -replace '\s+','\s+' }
	) -join '|'))"
}

Function DefaultWSL {
	wsl -l `
	| %{
		#wsl returns strings in utf16 format, and powershell has no way of making it native
		#pwsh works in utf16 natively, yet $_[0] or $_[1] will be a null char, so on and so forth for every second character
		#bizarre
		$_ = $_ -replace '\0',''
		
		if ($_ -match '^(.*?)\s+\(Default\)$') {
			$Matches[1]
		}
	}
}

Filter RootCommand { Param($wsl)
	wsl `
		--distribution $wsl `
		--user root `
		-- bash -c $_
}

Function wslMount { Param(
	[Parameter(Mandatory=$true)][string[]]$drives,
	[Parameter(Mandatory=$true)][int]$count,
	[string]$wsl,
	[string]$mount,
	[string]$mapper,
	[string[]]$options,
	[string]$format
)
	$opts = ''
	if ($options) {
		$opts = " -o $($options -join ',')"
	}
	$matcher = ToMatcher -names $drives
	if (!$wsl) {
		$wsl = DefaultWSL
	}
	if (!$mount) {
		$mount = $mapper
		if (!$mapper) {
			throw 'Must use at least one of mount name or luks mapper identifier'
		}
	}
	if ($mount -match '^[^/]') {
		$mount = '/mnt/wsl/' + $mount
	}

	$disks = GetDisks -matcher $matcher
	if ($disks.Count -ne $count) {
		throw 'Mismatched disks'
	}

	$disks
	"Attach drives to $wsl"
	if ($mapper) {
		"Using encryption via /dev/mapper/${mapper}X"
	}
	else {
		'With no encryption'
	}
	if ($format) {
		'THE DISKS WILL BE WIPED'
		(@($format) + ('disk1','disk2','...')) -join ' ' 
	}
	"Mount it as $mount"



	'','Proceed?'
	pause

	AttachDisks -wsl $wsl -disks $disks
	$devices = GetDevices -wsl $wsl -matcher $matcher
	
	
	
	if ($mapper) {
		'',('Encrypt?','Decrypt?')[!$format]
		pause

		$devices `
		| &{
			Begin {
				$index = -1
			}
			Process {
				++$index
				if ($format) {
					"cryptsetup luksFormat --type luks2 '$_'"
				}
				"cryptsetup luksOpen '$_' '$mapper$index'"
			}
		} `
		| RootCommand -wsl $wsl
		
		$devices = 0..($count - 1) `
		| %{
			"/dev/mapper/$mapper$_"
		}
	}
	
	
	
	if ($format) {
		'','Format?'
		pause
		
		(@($format) + $devices) -join ' ' `
		| RootCommand -wsl $wsl
	}
		
		
		
	'','Mount?'
	pause

	$devices `
	| %{
		"mkdir '$mount' 2>/dev/null && (mount$opts '$_' '$mount' || rmdir '$mount')"
	} `
	| RootCommand -wsl $wsl

	explorer "\\wsl`$\$wsl$($mount -replace '/','\')"



	'','Unmount?'
	pause
	
	"umount '$mount' && rmdir '$mount'" `
	| RootCommand -wsl $wsl
	
	
	
	'','Detach?'
	pause

	if ($mapper) {
		$devices `
		| %{
			"cryptsetup luksClose '$_'"
		} `
		| RootCommand -wsl $wsl
	}

	$disks `
	| %{
		"Detaching $_"
		wsl --unmount $_
	}



	'','Done!'
}