#=========================================================#
# Standardbibliothek für CoreShell Scripte                #
#=========================================================#

#
# Einen Script-Block im GUI-Thread ausführen
#
function Invoke-ForGui {
	param (
		[bool] $sync = $false, 
		[de.mastersign.shell.ScriptMethod] $method
	)
	
	if ($sync) {
		$method.InvokeForGuiSync($mainForm)
	} else {
		$method.InvokeForGuiAsync($mainForm)
	}
}

# Einen Script-Block asynchron im GUI-Thread ausführen
function guii ([de.mastersign.shell.ScriptMethod] $method) {
	Invoke-ForGui $false $method
}

# Einen Script-Block synchron im GUI-Thread ausführen
function guiis ([de.mastersign.shell.ScriptMethod] $method) {
	Invoke-ForGui $true $method
}

#
# DynamicNodes beenden
#
function Quit-DynamicNodes {
	guiis { 
		$mainForm.Close() 
	}
}

#
# Sendet eine Fehlernachricht an das Systemprotokoll
#
function Write-DNLog {
	param (
		[string] $msg,
		[Diagnostics.TraceEventType] $type = "Information",
		[int] $id = 0
	)
	
	switch ($type)
	{
		"Error" { [DynamicNode.Shell.ShellTrace]::Error($id, $msg) }
		"Warning" { [DynamicNode.Shell.ShellTrace]::Warning($id, $msg) }
		"Information" { [DynamicNode.Shell.ShellTrace]::Info($id, $msg) }
		"Verbose" { [DynamicNode.Shell.ShellTrace]::Verbose($msg) }
		default { [DynamicNode.Shell.ShellTrace]::Info($id, $msg) }
	}
}

#
# Einen neuen Knoten erzeugen
#
function New-Node([string] $typeName, [string] $name) {
	New-Item $name -ItemType $typeName
}

#
# Einen Knoten löschen
#
function Remove-Node([string] $path) {
	$n = Get-Item $path
	if (-not $n -is [DynamicNode.Core.INode]) {
		throw "Der angegebene Pfad beschreibt keinen Knoten.`n`t$path"
	}
	$n.Parent.Children.Remove($n)
}

#
# Prüfen, ob zwei Anschlüsse verbunden werden dürfen
#
function Check-Connectability([string] $portPath1, [string] $portPath2) {
	$p1 = Get-Item $portPath1
	$p2 = Get-Item $portPath2
	if (-not $p1) {
		throw "Anschluss '$portPath1' wurde nicht gefunden."
	}
	if (-not $p2) {
		throw "Anschluss '$portPath2' wurde nicht gefunden."
	}
	$selectedType = $null
	return $p1.IsConnectableTo($p2, ([REF]$selectedType))
}

#
# Zwei Anschlüsse verbinden
#
function Connect-Ports([string] $portPath1, [string] $portPath2) {
	$p1 = Get-Item $portPath1
	$p2 = Get-Item $portPath2
	if (-not $p1) {
		throw "Anschluss '$portPath1' wurde nicht gefunden."
	}
	if (-not $p2) {
		throw "Anschluss '$portPath2' wurde nicht gefunden."
	}
	return $p1.TryConnect($p2)
}

#
# Prüft, ob zwei Anschlüsse verbunden sind
#
function Check-Connection([string] $portPath1, [string] $portPath2) {
	$p1 = Get-Item $portPath1
	$p2 = Get-Item $portPath2
	if (-not $p1) {
		throw "Anschluss '$portPath1' wurde nicht gefunden."
	}
	if (-not $p2) {
		throw "Anschluss '$portPath2' wurde nicht gefunden."
	}
	if (($p1 -is [DynamicNode.Core.InPort]) `
		-and ($p2 -is [DynamicNode.Core.OutPort])) {
		return $p1.ConnectedOutPort -eq $p2
	} elseif (($p1 -is [DynamicNode.Core.OutPort]) `
		-and ($p2 -is [DynamicNode.Core.InPort])) {
		return $p2.ConnectedOutPort -eq $p1
	} else {
		return $false
	}
}

#
# Zwei Anschlüsse trennen
#
function Disconnect-Ports([string] $portPath1, [string] $portPath2) {
	$p1 = Get-Item $portPath1
	$p2 = Get-Item $portPath2
	if (-not $p1) {
		throw "Anschluss '$portPath1' wurde nicht gefunden."
	}
	if (-not $p2) {
		throw "Anschluss '$portPath2' wurde nicht gefunden."
	}
	if ($p1 -is [DynamicNode.Core.InPort]) {
		$p1.Disconnect()
	} elseif ($p2 -is [DynamicNode.Core.InPort]) {
		$p2.Disconnect()
	}
}
