#region Variables
$servername = $args[0]
$prodname = $args[1]

$ANCHOR_TAG_PATTERN = "<\s*a\s*[^>]*?href\s*=\s*[`"']*([^`"'>]+)[^>]*?>"
$Now = Get-Date
$DT = Get-Date -Format "yyyy-MM-dd_HHmm"
# $OutFilePath = "$PSScriptRoot\Invalid-Links_$servername" + "_$DT.txt"
# $OutFilePathBase = "\\zusscgrcprodwebhelp.file.core.windows.net\webhelp\dev\scripts\LinkChecker\Results"
$OutFilePathBase = "C:\DITA\scripts\LinkChecker\Results"
$OutFilePath = "$OutFilePathBase\Invalid-Links_$servername" + "_$DT.txt"
$LinkCount = 0


if (($servername -eq $null -and $prodname -eq $null) -or ($servername -eq "help"))
{
    Write-Host "Cannot continue. You have not provided an environment."
    Write-Host "Command examples:"
    Write-Host "powershell.exe .\ParseLinks.ps1 stg          (checks links in all of stg server)"
    Write-Host "powershell.exe .\ParseLinks.ps1 stg engine   (checks links in the staging server's Engine folder )"
    Write-Host ""
    Write-Host "Possible server environments:   dev, stg, tst-expere, tst, prod"
    Write-Host "Possible product roots:         assumptions, authoring, bbe, billing, c1, c1admin, commlending, cfgportal, " +
                "dgs, dgsi, dgsjh, disaster, docprep, docprepi, docportal, docviewer, eds, edsi, engine, eoriginal, ezconfig, " +
                "fullfillment, i32, infodev, interface, ira, mortgage, oauth, onlineapp, oppsa, oppsaop, pds, pnp, " +
                "sdx, secadmin, settlement, statelink, vanceo, wkes, wkhe, wkis, workflow"
    Exit
}

switch ( $servername )
{
    dev { $SiteRoot = "\\zusscgrcprodwebhelp.file.core.windows.net\webhelp\dev" }
    stg { $SiteRoot = "\\zusscgrcprodwebhelp.file.core.windows.net\webhelp\stg" }
    tst-expere { $SiteRoot = "\\zusscgrcprodwebhelp.file.core.windows.net\webhelp\tst-expere" }
    tst { $SiteRoot = "\\zusscgrcprodwebhelp.file.core.windows.net\webhelp\tst" }
    prod { $SiteRoot = "\\zusscgrcprodwebhelp.file.core.windows.net\webhelp\prod" }
}

switch ( $prodname )
{
    assumptions { $ProdRoot = "\Assumptions" }
    authoring { $ProdRoot = "\Expere\Authoring" }
    bbe { $ProdRoot = "\BBE" }
    billing { $ProdRoot = "\Billing-Administration" }
    c1 { $ProdRoot = "\C1" }
    c1admin { $ProdRoot = "\C1Administration" }
    cfgportal { $ProdRoot = "\ConfigurationPortal" }
    commlending { $ProdRoot = "\CommercialLending" }
    dgs { $ProdRoot = "\DGS" }
    dgsi { $ProdRoot = "\DGS-Internal" }
    dgsjh { $ProdRoot = "\DGS-Jack-Henry" }
    disaster { $ProdRoot = "\DisasterRecovery" }
    docprep { $ProdRoot = "\DocPrep" }
    docprepi { $ProdRoot = "\DocPrep-Internal" }
    docportal { $ProdRoot = "\Expere\DocumentPortal" }
    docviewer { $ProdRoot = "\DocViewer" }
    eds { $ProdRoot = "\EDS" }
    edsi { $ProdRoot = "\EDS-Internal" }
    engine { $ProdRoot = "\Expere\Engine" }
    eoriginal { $ProdRoot = "\Expere\eOriginal" }
    ezconfig { $ProdRoot = "\ExpereEZConfig" }
    fullfillment { $ProdRoot = "\FullfillmentManager" }
    i32 { $ProdRoot = "\I-32" }
    infodev { $ProdRoot = "\InfoDev" }
    interface { $ProdRoot = "\InterfaceManager" }
    ira { $ProdRoot = "\IRALibrary" }
    mortgage { $ProdRoot = "\Mortgage" }
    oauth { $ProdRoot = "\OAuth" }
    onlineapp { $ProdRoot = "\OnlineApplication" }
    oppsa { $ProdRoot = "\OPPSA" }
    oppsaop { $ProdRoot = "\OPPSA-OnPrem" }
    pds { $ProdRoot = "\ProductDownloadSite" }
    pnp { $ProdRoot = "\PnP" }
    sdx { $ProdRoot = "\SDX" }
    secadmin { $ProdRoot = "\SecurityAdministration" }
    settlement { $ProdRoot = "\SettlementServices" }
    statelink { $ProdRoot = "\StateLink" }
    vanceo { $ProdRoot = "\Vanceo" }
    wkes { $ProdRoot = "\WoltersKluwer_E-Sign" }
    wkhe { $ProdRoot = "\WK-Hosted-Expere" }
    wkis { $ProdRoot = "\WK-IntegratedSolutions" }
    workflow { $ProdRoot = "\Workflow" }
}
$ProdRoot = $ProdRoot.replace('\', '/')

if ( $prodname -ne $null)
{
    $SiteRoot = $SiteRoot + $ProdRoot
    $OutFilePath = "$OutFilePathBase\Invalid-Links_$servername-$prodname" + "_$DT.txt"
}
Write-Host "Checking links on: $SiteRoot..."

#endregion

#region Helper Functions
function GetMatches([string] $content, [string] $regex)
{
    $returnMatches = new-object System.Collections.ArrayList
    $resultingMatches = [Regex]::Matches($content, $regex, "IgnoreCase")
    foreach($match in $resultingMatches)
    {
        $cleanedMatch = $match.Groups[1].Value.Trim()
        [void] $returnMatches.Add($cleanedMatch)
    }
    $returnMatches
}

if ([System.IO.File]::Exists($OutFilePath))
{
    [System.IO.File]::Delete($OutFilePath)
}

function Write-Line
{
    Param
    (
        [string] $line
    )

    $Line | Out-File $OutFilePath -Append
}

#endregion

#region Execution Hook Functions

function ShouldIncludeLink($link)
{
    # Purpose: Determine if the "href" value is something we should care about...

    if ($link.startsWith("#") -or 
        $link.startsWith("http://www.oxygenxml.com") -or 
        $link.startsWith("javascript:") -or 
        $link.startsWith("mailto:") -or
        $link.startsWith("/about_cookies") -or
        (($prodname -ne $null) -and (-not ($link.startsWith($ProdRoot))))
        )
    {
        return $false
    }
    else
    {
        return $true
    }
}

function GetFullPath($info, $tag)
{
    # Purpose: Gets the full path of whatever's in the "href" value for each tag.

    # TODO: Add more cases as needed...

    $Root = $Info.Directorys

    if ($tag.startsWith("/"))
    {
        # $Root = $SiteRoot -replace '/[^/]*$'
        $Root = $SiteRoot | Split-Path
        if ($prodname -eq 'authoring' ||
            $prodname -eq 'engine' ||
            $prodname -eq 'eoriginal')
        {
            $Root = $Root | Split-Path
        }
    }

    # if ($tag.startsWith("../"))
    # {
    #     $filenameBase = Split-Path -path $filePath
    #     $Root = $filenameBase
    # }
    # Write-Host "Root =     $Root"
    # Write-Host "SiteRoot = $SiteRoot"
    # Write-Host "tag =      $tag"
    $filePath = $(Join-Path -Path $Root -ChildPath $tag.replace('/', '\'))
    # Write-Host "(Line 138) $filePath"

    return [System.IO.Path]::GetFullPath($filePath)
}

function CleanTag($tag)
{
    # Purpose: Cleans the "href" attribute value for each "a" tag

    # TODO: Add more cases as needed...

    # CASE: foobar.html#r7457237 --> foobar.html

    if ($tag.contains("#"))
    {
        $parts = $tag.split('#')

        if ($parts.count -gt 1)
        {
            $tag = $parts[0].trim()
        }
    }

    if ($tag.contains("?"))
    {
        $parts = $tag.split('?')

        if ($parts.count -gt 1)
        {
            $tag = $parts[0].trim()
        }
    }

    # CASE: Foo%20Bar.html --> Foo Bar.html
    $tag = $tag.replace("%20", " ")

    return $tag
}

#endregion

#region MAIN

# --------------------------------------------------
# Read all .html files and parse anchor tag hrefs
# --------------------------------------------------

Write-Line "==================================="
Write-Line $Now
Write-Line "Report of invalid links for site root of:"
Write-Line $SiteRoot
Write-Line "==================================="
Write-Line ""

foreach ($file in $([System.IO.Directory]::EnumerateFiles($SiteRoot, "*.html", "AllDirectories")))
{
    $info = New-Object System.IO.FileInfo $file

    $text = $(Get-Content -Raw $file)
    $anchorTags = @(GetMatches $text $ANCHOR_TAG_PATTERN)
    $links = [System.Collections.ArrayList]@()

    foreach ($tag in $anchorTags | Where-Object { $(ShouldIncludeLink -link $_) })
    {
        $cleanTag = CleanTag -tag $tag
        $filePath = GetFullPath -info $info -tag $cleanTag

        if (-not [System.IO.File]::Exists($filePath))
        {
            $links.Add($cleanTag) | Out-Null
        }
    }

    if ($links.count -gt 0)
    {
        $relativePath = [System.IO.Path]::GetRelativePath($SiteRoot, $file)

        # Write-Line $relativePath
        # Write-Line ""
        Write-Line "Source file: $file"
        foreach ($link in $links)
        {
            Write-Line "- $link"
            $LinkCount++
        }

        Write-Line ""
    }
}

$EndTime = Get-Date
$Duration = $EndTime-$Now
Write-Line "==================================="
Write-Line "Start time: $Now"
Write-Line "End time: $EndTime"
Write-Line "Total time: $Duration"
Write-Line "Total # of invalid links: $LinkCount"
Write-Line "==================================="
Write-Host "==================================="
Write-Host "Start time: $Now"
Write-Host "End time: $EndTime"
Write-Host "Total time: $Duration"
Write-Host "Total # of invalid links: $LinkCount"
Write-Host "==================================="
#endregion