Param(
        [parameter(Position=0,Mandatory=$true)]
        [ValidateSet("pdisk", "vdisk", "bbu", "adapter")]
        [alias("m")]
        [String]
        $mode
	,
        [parameter()]
        [ValidateRange(0,5)]
        [alias("a","adp")]
        [int]
		$adapter
)

$CLI = "C:\Program Files\Zabbix Agent\bin\perccli64.exe"


function disco_adp() {
	$number_of_adapters     = [int](& $CLI -adpCount -NoLog | Select-String "Controller Count: (\d+)" -AllMatches | % {$_.Matches} | % {$_.groups[1].value})
	$out = '['
	$i = 1
	for ($adapter_id = 0; $adapter_id -lt $number_of_adapters; $adapter_id++) {
		$out = $out + "{`"{#MEGARAID_ADP}`": `"$adapter_id`"}"
		if ($i -lt $number_of_adapters){
			$out = $out + ','
		}
		$i++
	}
	$out = $out + ']'
	Write-Host $out
}

function disco_bbu() {
	$battery_units      = @{}
	$number_of_adapters = [int](& $CLI -adpCount -NoLog | Select-String "Controller Count: (\d+)" -AllMatches | % {$_.Matches} | % {$_.groups[1].value})
	for ($adapter_id = 0; $adapter_id -lt $number_of_adapters; $adapter_id++) {
		$bbu_is_missing = (& $CLI -AdpBbuCmd -GetBbuStatus -a $adapter -NoLog | Select-String ".*Get BBU Status Failed.*" | % {$_.Matches})
		if (!$bbu_is_missing) {
			$battery_units.Add($adapter,"{ `"{#ADAPTER_ID}`":`"$adapter`" }")
		}
	}
	$out = '['
	$i = 1
	foreach ($battery_unit in $battery_units.Keys){
		$out = $out + "$($battery_units.item($battery_unit))"
		if ($i -lt $battery_units.Count){
			$out = $out + ","
		}
	}
	$out = $out + ']'
	Write-Host $out
}

function disco_vdisk() {
	$virtual_drives = @{}
	# check IDs for configured RAID volumes (IDs could be sequential, or not)
    $tmp_file = Join-Path ${env:temp} "raid_vdrives-$(Get-Date -Format yyyy-MM-dd-HH-mm-ss).tmp"
    & $CLI -LDinfo -Lall -a $adapter -NoLog | Out-File $tmp_file
    [regex]$regex_vd_id = "^\s*Virtual\sDrive:\s(\d+)\s.*$"
    $reader             = [System.IO.File]::OpenText($tmp_file)
    $vdrive_id          = -1;
    try {
        for(;;) {
            $line = $reader.ReadLine()
            if ($line -eq $null) { break }
            if (($regex_vd_id.isMatch($line)) -eq $True) {
                $vdrive_id          = $regex_vd_id.Matches($line) | % {$_.groups[1].value}
                $virtual_drives.Add("$adapter-$vdrive_id","{ `"{#VDRIVE_ID}`":`"$vdrive_id`", `"{#ADAPTER_ID}`":`"$adapter`" }")
            } else {
                Continue
            }
        }
    }
    finally {
        $reader.Close()
    }
    remove-item $tmp_file
	$out = '['
	$i = 1
	foreach ($virtual_drive in $virtual_drives.Keys) {
		$out = $out + "$($virtual_drives.Item($virtual_drive))"
        if ($i -lt $virtual_drives.Count) {
            $out = $out + ","
        }
        $i++
	}
	$out = $out + ']'
	Write-Host $out
}

function disco_pdisk() {
	$physical_drives = @{}
	# ========
    # List all physical drives
    # ========
    $check_next_line        = 0
    [regex]$regex_enc       = "^\s*Enclosure\sDevice\sID:\s(\d+)$"
    [regex]$regex_enc_na    = "^\s*Enclosure\sDevice\sID:\sN\/A$"
    [regex]$regex_slot      = "^\s*Slot\sNumber:\s(\d+)$"

    $tmp_file   = Join-Path ${env:temp} "raid_enclosures-$(Get-Date -Format yyyy-MM-dd-HH-mm-ss).tmp"
    & $CLI -pdlist -a $adapter -NoLog | Out-File $tmp_file
    $reader     = [System.IO.File]::OpenText($tmp_file)

    # Determine Slot Number for each drive on enclosure
    $enclosure_id = -1;
    try {
        for(;;) {
            $line = $reader.ReadLine()
            if ($line -eq $null) { break }
            # Line contains enc id, next line is slot id
            if (($regex_enc.isMatch($line)) -eq $True) {
                $enclosure_id       = $regex_enc.Matches($line) | % {$_.groups[1].value}
                $check_next_line    = 1
            } elseif (($regex_enc_na.isMatch($line)) -eq $True) {
                # This can happen, if embedded raid controller is in use, there are drives and logical disks, but no enclosures
                $enclosure_id       = 2989 # 0xBAD, :( magic hack
                $check_next_line    = 1
            } elseif ((($regex_slot.isMatch($line)) -eq $True) -and ($check_next_line -eq 1) -and ($enclosure_id -ne -1)) {
                $drive_id           = $regex_slot.Matches($line) | % {$_.groups[1].value}
                $physical_drives.Add("$adapter-$enclosure_id-$drive_id","{ `"{#ENCLOSURE_ID}`":`"$enclosure_id`", `"{#PDRIVE_ID}`":`"$drive_id`", `"{#ADAPTER_ID}`":`"$adapter`" }")
                $check_next_line    = 0
                $enclosure_id       = -1
            } else {
                Continue
            }
        }
    }
    finally {
        $reader.Close()
    }
    remove-item $tmp_file
	
	$out = '['
	$i = 1
	foreach ($physical_drive in $physical_drives.Keys) {
		$out = $out + "$($physical_drives.Item($physical_drive))"
        if ($i -lt $physical_drives.Count) {
            $out = $out + ","
        }
        $i++
	}
	$out = $out + ']'
	Write-Host $out
}

switch ($mode) {
	"adapter"  { disco_adp }
	"bbu"      { disco_bbu }
	"vdisk"    { disco_vdisk }
	"pdisk"    { disco_pdisk }
}
