ReCrutch.Tools.psm1

$ReCrCommonScriptBlock = {
    $ReCr = @{}
    Set-Variable -Name "ReCr" -Value $ReCr -Scope Global

    #[enum]::GetValues([System.ConsoleColor]) | Foreach-Object {Write-Host $_ -ForegroundColor $_}
    $ReCr.ConsoleColors = @{
        trace = [System.ConsoleColor]::DarkGray
        verbose = [System.ConsoleColor]::Cyan
        verbose_remove = [System.ConsoleColor]::DarkRed
        verbose_add = [System.ConsoleColor]::DarkGreen
        delimeter = [System.ConsoleColor]::DarkYellow
        errorStackTrace = [System.ConsoleColor]::Gray
        errorType = [System.ConsoleColor]::DarkRed
        errorMessage = [System.ConsoleColor]::Red
        high_remove = [System.ConsoleColor]::Red
        high_add = [System.ConsoleColor]::Green
        process = [System.ConsoleColor]::DarkYellow
        header2 = [System.ConsoleColor]::Magenta
        header1 = [System.ConsoleColor]::Yellow
    }

    $ReCr.NewLines = @{
        beforeError = 0
        afterError = 0
        beforeHeader1 = 3
        beforeHeader2 = 0
        standart = 1
    }

    $ReCr.Options = @{
        SetReCrReplaceContenFileVerbose = $false
    }

    $ReCr.indent = 0

    $ReCr.Commands = @()

    function global:Write-Host-New-Line([int] $number)
    {
        if($number -eq $null)
        {
            $number = 1
        }

        for($i = 0; $i -lt $number; $i++)
        {
            Write-Host ""
        }
    }

    function global:Write-Host-Indent([int] $indent, [string]$message, $foregroundColor, $NoNewline, $firstLineNoIndent)
    {
        $spaces = ($ReCr.indent + $indent) * 2

        if($NoNewline -eq $null)
        {
            $NoNewline = $false
        }
        if($firstLineNoIndent -eq $null)
        {
            $firstLineNoIndent = $false
        }

        $arr = $message.Split(@("`r", "`n"), [System.StringSplitOptions]::RemoveEmptyEntries)
        foreach($line in $arr)
        {
            if($firstLineNoIndent -ne $true)
            {
                for($i = 0; $i -lt $spaces; $i++)
                {
                    Write-Host " " -NoNewline
                }
            }

            $firstLineNoIndent = $false

            if($line.Contains("[color:") -eq $false)
            {
                Write-Host $line -ForegroundColor $foregroundColor -NoNewline:$NoNewline
            }
            else
            {
                $splitLine = @()
                $tempStr = $line
                while($true)
                {
                    $ind = $tempStr.IndexOf("[color:", $index)
                    if($ind -lt 0)
                    {
                        Write-Host $tempStr -ForegroundColor $foregroundColor -NoNewline:$NoNewline
                        break
                    }

                    $str = $tempStr.Substring(0, $ind)
                    Write-Host $str -ForegroundColor $foregroundColor -NoNewline

                    $ind2 = $tempStr.IndexOf("]", $ind)
                    if($ind2 -lt 0)
                    {
                        throw New-Object System.Exception("error parse, not find ]")
                    }

                    $color = $tempStr.Substring($ind, $ind2 - $ind)
                    $color = $color.Replace("[color:", "").Replace("]", "")

                    $foregroundColor = [Enum]::Parse([System.ConsoleColor], $color)

                    $tempStr = $tempStr.Substring($ind2 + 1)
                }
            }
        }
    }

    function global:Set-ReCrColor($foregroundColor)
    {
        "[color:$foregroundColor]"
    }

    function global:Show-ReCrError([string] $message, [System.Exception] $ex)
    {
        Write-Host-New-Line $ReCr.NewLines.beforeError
        Write-Host-Indent 0 "--------------------------------------------" -ForegroundColor:$ReCr.ConsoleColors.delimeter
        Write-Host-Indent 0 "Error: $message" -ForegroundColor:$ReCr.ConsoleColors.errorMessage

        $arr = @()
        $e = $ex
        while($e -ne $null)
        {
            $arr += $e
            $e = $e.InnerException
        }

        #[Object[]]::Reverse($arr)

        $indent = 0
        foreach($e in $arr)
        {
            $indent++
            Write-Host-Indent $indent "--- Exception" -ForegroundColor:$ReCr.ConsoleColors.delimeter -NoNewline:$true
            Write-Host " Type: $($e.GetType())" -ForegroundColor:$ReCr.ConsoleColors.errorType
            Write-Host-Indent ($indent+2) "$($e.Message)" -ForegroundColor:$ReCr.ConsoleColors.errorMessage
            Write-Host-Indent ($indent+1) "StackTrace:" -ForegroundColor:$ReCr.ConsoleColors.delimeter
            Write-Host-Indent ($indent+1) "$($e.StackTrace)" -ForegroundColor:$ReCr.ConsoleColors.errorStackTrace
        }

        Write-Host-Indent 0 "--------------------------------------------" -ForegroundColor:$ReCr.ConsoleColors.delimeter
        Write-Host-New-Line $ReCr.NewLines.afterError
    }
}


& $ReCrCommonScriptBlock


$ReCr.Commands += @{
    index = 0
    cmd = "Show-ReCr-Commands"
    desc = "shows the commands available for execution"
}
function Show-ReCrCommands()
{
    Write-Host-New-Line $ReCr.NewLines.beforeHeader1
    Write-Host-Indent 0 "Команды для выполнения:" -ForegroundColor:$ReCr.ConsoleColors.header1

    foreach($cmd in ($ReCr.Commands | Sort-Object { $_.index }))
    {
        Write-Host-New-Line $ReCr.NewLines.standart
        Write-Host-Indent 1 "$($cmd.cmd)" -ForegroundColor:$ReCr.ConsoleColors.high_add -NoNewline:$true
        Write-Host-Indent 2 " - $($cmd.desc)" -ForegroundColor:$ReCr.ConsoleColors.verbose -firstLineNoIndent:$true
    }
}

function Invoke-ReCr($throwError, $scriptBlock)
{
    try
    {
        & $scriptBlock
    }
    catch
    {
        Show-ReCrError "$($scriptBlock.ToString())" $_.Exception
        if($throwError -eq $true)
        {
            throw New-Object System.Exception("Error in script block:`r`n$($scriptBlock.ToString())", $_.Exception)
        }
    }
}

function Get-ReCrScriptPath($MyCommand, $overridePath)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1

        $sp = $MyCommand.Path
        Write-Host-Indent 1 "ScriptPath: $(Set-ReCrColor $ReCr.ConsoleColors.verbose_add)$sp" -ForegroundColor:$ReCr.ConsoleColors.verbose
        if($overridePath -ne $null)
        {
            $sp = $overridePath
            Write-Host-Indent 1 "ScriptPath overridePath: $(Set-ReCrColor $ReCr.ConsoleColors.verbose_add)$sp" -ForegroundColor:$ReCr.ConsoleColors.verbose
        }

        if($sp -eq $null)
        {
            throw new-object System.Exception ("ScriptPath - specify the full path to the current file")
        }

        $sfp = split-path -parent $sp
        $sfp = ($sfp + "\")
        Write-Host-Indent 1 "ScriptFolderPath: $(Set-ReCrColor $ReCr.ConsoleColors.verbose_add)$sfp" -ForegroundColor:$ReCr.ConsoleColors.verbose

        $sfp
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Start-ReCrCmd($workingDirectory, $arguments)
{
    try
    {
        $pinfo = New-Object System.Diagnostics.ProcessStartInfo
        $pinfo.FileName = "$env:comspec"
        $pinfo.WorkingDirectory = ("$workingDirectory".TrimEnd("\") + "\")
        $pinfo.Arguments = $arguments

        $p = New-Object System.Diagnostics.Process
        $p.StartInfo = $pinfo
        $p.Start() | Out-Null

        Write-Host "Start process $($pinfo.FileName) $($pinfo.Arguments)"

        $p.WaitForExit()
        Write-Host "Process exit code: $($p.ExitCode)"

        if($p.ExitCode -ne 555)
        {
            throw [System.Exception] "Process $($pinfo.FileName) $($pinfo.Arguments)
    Exit code: $($p.ExitCode)"

        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Set-ReCrReplaceContenFile([System.String] $file, [System.Array] $patternReplacment)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1
        Write-Host-Indent 1 "$file $(ConvertTo-Json $patternReplacment -Compress)" -ForegroundColor:$ReCr.ConsoleColors.verbose

        if((Test-Path $file) -ne $true)
        {
            throw [System.Exception] "Not found file '$file'"
        }

        if($patternReplacment -eq $null)
        {
            throw [System.Exception] "requery `$patternReplacment"
        }

        if($patternReplacment.Count -lt 1)
        {
            throw [System.Exception] "requery `$patternReplacment Count >= 1"
        }

        #$srcStr = Get-Content $file | Out-String
        $srcStr = [System.IO.File]::ReadAllText($file)
        $newStr = $srcStr

        $isSave = $false
        $index = -1;
        foreach($item in $patternReplacment)
        {
            $index++
            if([String]::IsNullOrWhiteSpace($item.pattern))
            {
                throw [System.Exception] "requery `$patternReplacment[$index].pattern"
            }

            if($item.replacment -eq $null)
            {
                throw [System.Exception] "requery `$patternReplacment[$index].replacment"
            }

            #""
            #""
            #"patternReplacment[$index]"
            #$item

            [Regex]::Matches($newStr, $item.pattern)
            $newStr = [Regex]::Replace($newStr, $item.pattern, $item.replacment)
        }

        if($srcStr -ne $newStr -and $ReCr.OptionsSetReCrReplaceContenFileVerbose -eq $true)
        {
            "---content before b"
            $srcStr
            "---content before e"

            "---content after b"
            $newStr
            "---content after e"
        }

        $isSave = $srcStr -ne $newStr

        if($isSave)
        {
            "save"
            #Set-Content -Path $file -Value $newStr
            [System.IO.File]::WriteAllText($file, $newStr)
        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Clear-ReCrFolder($path)
{
    if((Test-Path $path) -eq $false)
    {
        Write-Host-Indent 0 "Создание каталога $(Set-ReCrColor $ReCr.ConsoleColors.verbose_add)$path" -ForegroundColor:$ReCr.ConsoleColors.process
        $f = New-Item $path -type directory
    }
    else
    {
        Write-Host-Indent 0 "Очистка каталога $(Set-ReCrColor $ReCr.ConsoleColors.verbose_remove)$path" -ForegroundColor:$ReCr.ConsoleColors.process
        Remove-Item "$($path.TrimEnd("\"))\*" -Recurse:$true
    }
}

function Repair-ReCrUri([System.Uri] $uri){
    $UnEscapeDotsAndSlashes = 0x2000000;
    $SimpleUserSyntax = 0x20000;

    $type = $uri.GetType();
    $fieldInfo = $type.GetField("m_Syntax", ([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic));

    $uriParser = $fieldInfo.GetValue($uri);
    $typeUriParser = $uriParser.GetType().BaseType;
    $fieldInfo = $typeUriParser.GetField("m_Flags", ([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::FlattenHierarchy));
    $uriSyntaxFlags = $fieldInfo.GetValue($uriParser);

    $uriSyntaxFlags = $uriSyntaxFlags -band (-bnot $UnEscapeDotsAndSlashes);
    $uriSyntaxFlags = $uriSyntaxFlags -band (-bnot $SimpleUserSyntax);
    $fieldInfo.SetValue($uriParser, $uriSyntaxFlags);
}

Export-ModuleMember -function *