[CmdletBinding()]
param
(
    [Parameter(Mandatory=$false)]
    [string]$LogDir,

    [parameter(Mandatory=$false)]
    [boolean] $useServiceFabric=$false,

    [Parameter(Mandatory = $false)]
    [string]$ActivityId,

    [Parameter(Mandatory = $false)]
    [string]$RunbookId,

    [Parameter(Mandatory=$false)]
	[hashtable]$AxDRConnectionString,

    [Parameter(Mandatory=$false)]
	[string[]]$EnabledServicingFeatures,

    [Parameter(Mandatory=$false)]
	[Switch]$PreDowntime,

    [Parameter(Mandatory=$false)]
    [hashtable]$Credentials
)

# Pre-defined list of error messages for known customer induced issues
$knownErrorHash = @{
    "The CREATE UNIQUE INDEX statement terminated because a duplicate key" = 131079
    "Please drop the original field, sync the table" = 131089
    "extension cannot be applied to the base element" = 131090
    "is missing the following dependencies" = 131091
    "Method not found" = 131092
}

# Check pre check status
function IsPreCheckSucceeded ([string]$ActivityId)
{
  if(!$ActivityId)
  {
    return $false
  }

  $axDBUser = Get-DataAccessSqlUsr

  if($Credentials -and $Credentials[$($axDBUser)])  {
     $axDBPwd = $Credentials[$($axDBUser)]
     EventWrite-RunbookScriptTrace -Message "Using axdbadmin password from DSU parameters." -Component "servicing" -RunbookId $RunbookId| Out-Null
  }
  else{
     $axDBPwd = Get-DataAccessSqlPwd
     EventWrite-RunbookScriptTrace -Message "Using axdbadmin password from Web config." -Component "servicing" -RunbookId $RunbookId| Out-Null
  }
  
  $axDBDatabaseName = Get-DataAccessDatabase
  $axDBServer = Get-DataAccessDbServer

    $target_sqlParams = @{
		'Database' = $axDBDatabaseName
		'UserName' = $axDBUser
		'Password' = $axDBPwd
		'ServerInstance' = $axDBServer
		'EncryptConnection' = !(IsLocalServer($axDBServer))
		'QueryTimeout' = 0
	    }

    $target_sqlParams.Query = "Select top 1 Success from DBSyncExecStats where SyncStep = 'PreCheck' and RelatedActivityId = '$ActivityId' order by StartDateTime desc"

    try{
        # during first precheck on this environment table will not be exists so catch exception and consider running precheck.
        $result = Invoke-SqlCmd @target_sqlParams
    }
    catch
    {
        $warningMessage = "[$(Get-Date)]:Get pre check status failed, activity id: $ActivityId, Exception: [$($_.Exception)]"
        Write-Host $warningMessage
        EventWrite-RunbookScriptTrace -Message $warningMessage -Component "servicing" -RunbookId $RunbookId| Out-Null
    }

    if ($result -ne $null)
    {
        return $result.Success
    }

    return $false
}

# Run db sync precheck to evaluate DB Sync would fail or succeed.
function RunDBSyncPreCheck([string]$ActivityId, [hashtable]$AxDRConnectionString, [string[]]$EnabledServicingFeatures)
{
    if (!$EnabledServicingFeatures -or $EnabledServicingFeatures -notcontains "DBSyncPreCheck")
    { 
       EventWrite-RunbookScriptTrace -Message "DBSyncPreCheck feature is disabled. Skipping db sync pre check, activity id: $ActivityId" -Component "servicing"  -RunbookId $RunbookId| Out-Null
       return $false
    }

    # Check if previous precheck status for activity id
    if($ActivityId)
    {
        $PreCheckResult = IsPreCheckSucceeded -ActivityId $ActivityId
        if($PreCheckResult -eq $true) 
        {
           # For prod scenario precheck will run during preparation, so we do not need to run it again.
           EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Pre service check already succeeded for activity id: $ActivityId, Skipping precheck..." -Component "servicing" -RunbookId $RunbookId| Out-Null
           return $false
        }
     }

    # Run Precheck
    $currentDateTime = [DateTime]::UtcNow.ToString("yyyyMMddHHmmss")
    $logfile = Join-Path $LogDir "dbsyncprecheck_$currentDateTime.log"
    $errorfile = Join-Path $LogDir "dbsyncprecheck.error_$currentDateTime.log"
    Write-Host "Precheck Started..."
   
    if($PreDowntime -eq $true)
    {
      $aosWebServiceStagingPath = Get-AosServiceStagingPath
      $webroot = Join-Path -Path $aosWebServiceStagingPath -ChildPath "WebRoot"
      $PUVersion = Get-ProductPlatformBuildVersion -webroot:$webroot

      $metadatadir = Join-Path -Path $aosWebServiceStagingPath -ChildPath "PackagesLocalDirectory"
    }
    else
    {
      $PUVersion = (Get-ProductPlatformBuildVersion)
      $metadatadir = $(Get-AOSPackageDirectory)
    }

    Write-Host "AOS platform version is: $PUVersion"

    # If PU version >= PU34 then run precheck on secondary DB if exists.
    $runPrecheckOnSecondaryDB = $false
    if($PUVersion -ge 5629 -and $AxDRConnectionString -and $AxDRConnectionString['AxDRServerName'] -and $AxDRConnectionString['AxDRDatabaseName'])
    {
        $runPrecheckOnSecondaryDB =  $true
        $sqlServer =  $AxDRConnectionString['AxDRServerName']
        $sqlDB =  $AxDRConnectionString['AxDRDatabaseName']
        EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Running precheck on secondary DB" -Component "servicing" -RunbookId $RunbookId| Out-Null
    }

    # If platform version > PU35 then run precheck with deployment setup exe
    if ($PUVersion -gt 5644)
    {
        EventWrite-RunbookScriptTrace -Message "Running precheck with deployment setup exe, activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
        $deploymentSetupParameter = "-setupmode preservicecheck -syncmode precheck"
        
        if($ActivityId) 
        {
            $deploymentSetupParameter += " -activityid $ActivityId"
        }

        $deploySetupPs1 = Resolve-Path -Path $deploySetupPs1
        & $deploySetupPs1 -deploymentSetupParameter $deploymentSetupParameter -logfile $logfile -errorfile $errorfile -axDRServerName $sqlServer -axDRDatabaseName $sqlDB -isPreDowntime $PreDowntime | Out-Null
        
        EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Pre service check completed using deployment setup for activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
        return $true
    }
    
    EventWrite-RunbookScriptTrace -Message "Running precheck on Metadata dir: $metadatadir" -Component "servicing" -RunbookId $RunbookId| Out-Null

    # If platform version <= PU35 Run precheck with sync engine exe
    EventWrite-RunbookScriptTrace -Message "Running precheck with sync engine exe, activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null

    $sqlUser = Get-DataAccessSqlUsr
    if($Credentials -and $Credentials[$($sqlUser)]) {
      $sqlPwd = $Credentials[$($sqlUser)]
    }
    else {
      $sqlPwd = Get-DataAccessSqlPwd
    }

    if($runPrecheckOnSecondaryDB -eq $false){
        $sqlServer = Get-DataAccessDbServer
        $sqlDB = Get-DataAccessDatabase
    }

    $connectionString = "Data Source=$($sqlServer); " +
        "Integrated Security=False; " +
        "User Id=$($sqlUser); " +
        "Password='$($sqlPwd)'; " +
        "Initial Catalog=$($sqlDB)"
    
    $command = "$metadatadir\bin\syncengine.exe"
    $commandParameter = "-syncmode=precheck"
    $commandParameter += " -metadatabinaries=$metadatadir"
    $commandParameter +=  " -connect=`"$connectionString`""
    $commandParameter +=  " -enableParallelSync"
                
    if($ActivityId)
    {
        $commandParameter += " -relatedactivityid=$ActivityId"
    }

    $process = Start-Process $command $commandParameter -PassThru -Wait -RedirectStandardOutput "$logfile" -RedirectStandardError "$errorfile"
    Write-Host "Log file location: $logfile"
        
    if ($process.ExitCode -ne 0) {
        $deploymentSetupError = Get-Content "$errorfile"
        throw $deploymentSetupError
    }

    EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Pre service check completed using sync engine for activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
    return $true
}

$ErrorActionPreference = "stop"
Import-Module "$PSScriptRoot\AosEnvironmentUtilities.psm1" -Force -DisableNameChecking
Import-Module "$PSScriptRoot\CommonRollbackUtilities.psm1" -ArgumentList $useServiceFabric -DisableNameChecking

if(!$LogDir)
{
    $LogDir = $PSScriptRoot
}

$deploySetupPs1 = "$PSScriptRoot\TriggerDeploymentSetupEngine.ps1"

# PreCheck
try
{
    # This returns false if pre check skipped.
    $result = RunDBSyncPreCheck -ActivityId $ActivityId -AxDRConnectionString $AxDRConnectionString -EnabledServicingFeatures $EnabledServicingFeatures
   
    if($result -eq $true)
    {   
        $message = "[$(Get-Date)]: Pre service check succeeded for activity id: $ActivityId."
    }
    else
    {
      $message = "[$(Get-Date)]: Pre service check did not run, activity id: $ActivityId."
    }

    Write-Host $message
    EventWrite-RunbookScriptTrace -Message $message -Component "servicing" -RunbookId $RunbookId| Out-Null
}
catch
{
    $errorMessage = "[$(Get-Date)]: Pre service check failed for activity id: $ActivityId, Exception: [$($_.Exception)]"    
    EventWrite-RunbookScriptTrace -Message $errorMessage -Component "servicing" -RunbookId $RunbookId | Out-Null

    if ($EnabledServicingFeatures -and $EnabledServicingFeatures -contains "FailDBSyncOnPrecheckFailure")
    { 
       EventWrite-RunbookScriptTrace -Message "FailDBSyncOnPrecheckFailure feature is enabled and db sync pre-check is failed, activity id: $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null

       # Only fail in dbsync pre-check if the error message contains one of the known error strings
       foreach ($knownError in $knownErrorHash.GetEnumerator())
       {
          if($errorMessage.Contains($knownError.Name))
          {
            # In case precheck failure due to a known customer-induced error scenario we do not require PITR during rollback. In precheck success scenario full sync will run and that will calculate PITR required or not.
            Write-IsPITRRequiredDuringRollback -PitrRequired 'false'

            EventWrite-RunbookScriptTrace -Message "DBSync pre-check failed due to a known customer induced error, error code: $($knownError.Value), activity id: $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
            throw $errorMessage
          }
       }
    }
}
# SIG # Begin signature block
# MIIsDwYJKoZIhvcNAQcCoIIsADCCK/wCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDf8pNtqZY7VDtd
# JiquVayV4+X8rN+4YqEWHTNh3X0wYqCCEX0wggiNMIIHdaADAgECAhM2AAACAR26
# 8SCNUOBoAAIAAAIBMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH
# QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe
# Fw0yNDExMDgxMjQ0MTRaFw0yNTExMDgxMjQ0MTRaMCQxIjAgBgNVBAMTGU1pY3Jv
# c29mdCBBenVyZSBDb2RlIFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
# AoIBAQC5EbpMULKgL3ArJn1rQqUye5Mzq2Eqlu0Ov9Vv2X+MvePQtXj4Cr7dLpJO
# VjPrUvirL6Jn8gYuDRxhVZbj3s81AfC8wq0sC/928aXCleSUDwX4scwK7vbpur2+
# TJm0WZ0E1gk8VY1bAjG9G3sQ2A+bpcMaBu7soLLH0ofyYzf6cl9irH3iHAw1ZucU
# mpROzEZcn3cmcxNwS0P2MX1nPE3qJEPoa3odBFZd5RXfDo7ro62MeNVjR/4bPjic
# IcnT/G0wWEXwKwTOkxFHibmmbhgfWAxDh75LZMYeLSeGkXhhBgQ/7Y11swZdaK3l
# okxcrV7d6jus7is+p6o8nep1OGGrAgMBAAGjggWZMIIFlTApBgkrBgEEAYI3FQoE
# HDAaMAwGCisGAQQBgjdbAQEwCgYIKwYBBQUHAwMwPQYJKwYBBAGCNxUHBDAwLgYm
# KwYBBAGCNxUIhpDjDYTVtHiE8Ys+hZvdFs6dEoFgg93NZoaUjDICAWQCAQ4wggJ2
# BggrBgEFBQcBAQSCAmgwggJkMGIGCCsGAQUFBzAChlZodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDEu
# YW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUy
# MDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDIuYW1lLmdibC9haWEv
# QlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBS
# BggrBgEFBQcwAoZGaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAx
# LkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZG
# aHR0cDovL2NybDQuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDCBrQYIKwYBBQUHMAKGgaBsZGFwOi8vL0NO
# PUFNRSUyMENTJTIwQ0ElMjAwMSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2Vy
# dmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1BTUUsREM9R0JM
# P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0
# aG9yaXR5MB0GA1UdDgQWBBSOzWIbg/0woPHoJiGbNef2gihnJDAOBgNVHQ8BAf8E
# BAMCB4AwVAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5k
# IE9wZXJhdGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjM2MTY3KzUwMzE2NTCCAeYG
# A1UdHwSCAd0wggHZMIIB1aCCAdGgggHNhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5j
# b20vcGtpaW5mcmEvQ1JML0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6
# Ly9jcmwxLmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0
# dHA6Ly9jcmwyLmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyG
# MWh0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5j
# cmyGMWh0dHA6Ly9jcmw0LmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgy
# KS5jcmyGgb1sZGFwOi8vL0NOPUFNRSUyMENTJTIwQ0ElMjAwMSgyKSxDTj1CWTJQ
# S0lDU0NBMDEsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNl
# cnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9QU1FLERDPUdCTD9jZXJ0aWZpY2F0
# ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9u
# UG9pbnQwHwYDVR0jBBgwFoAUllGE4Gtve/7YBqvD8oXmKa5q+dQwHwYDVR0lBBgw
# FgYKKwYBBAGCN1sBAQYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBABAaRi/Y
# mQnOw4MrZVaGuauVsykbusUmfa8tbfFNYfqqGhlJhBp8cWnpJnc39N3MDq22orPd
# dbidV8+YPxQ8FyhqFIkGKlV2WoD9kQV5LH+1RapE1nrHrGWH+vFdCcIy/X81ARIZ
# 2q3VHjNXQzMg+6vAJNMQRZIjk5pE/3YQvCNUOABt9gYFd8GEnTMeBaJaQibKB0o+
# 8tPKWRpse5J4/O4/Yj3dwI5YYmNPUFerhszwU6IXH/k3EwvgbFVCYCgtl6vckET8
# 36Ph/bJEA1uKmsFhtTAj8xE2USF9OHKFietrYEmA3aP0eIkyjRmZGRcla5P9fS62
# o2/gYAp0+NCn7C0wggjoMIIG0KADAgECAhMfAAAAUeqP9pxzDKg7AAAAAABRMA0G
# CSqGSIb3DQEBCwUAMDwxEzARBgoJkiaJk/IsZAEZFgNHQkwxEzARBgoJkiaJk/Is
# ZAEZFgNBTUUxEDAOBgNVBAMTB2FtZXJvb3QwHhcNMjEwNTIxMTg0NDE0WhcNMjYw
# NTIxMTg1NDE0WjBBMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQB
# GRYDQU1FMRUwEwYDVQQDEwxBTUUgQ1MgQ0EgMDEwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQDJmlIJfQGejVbXKpcyFPoFSUllalrinfEV6JMc7i+bZDoL
# 9rNHnHDGfJgeuRIYO1LY/1f4oMTrhXbSaYRCS5vGc8145WcTZG908bGDCWr4GFLc
# 411WxA+Pv2rteAcz0eHMH36qTQ8L0o3XOb2n+x7KJFLokXV1s6pF/WlSXsUBXGaC
# IIWBXyEchv+sM9eKDsUOLdLTITHYJQNWkiryMSEbxqdQUTVZjEz6eLRLkofDAo8p
# XirIYOgM770CYOiZrcKHK7lYOVblx22pdNawY8Te6a2dfoCaWV1QUuazg5VHiC4p
# /6fksgEILptOKhx9c+iapiNhMrHsAYx9pUtppeaFAgMBAAGjggTcMIIE2DASBgkr
# BgEEAYI3FQEEBQIDAgACMCMGCSsGAQQBgjcVAgQWBBQSaCRCIUfL1Gu+Mc8gpMAL
# I38/RzAdBgNVHQ4EFgQUllGE4Gtve/7YBqvD8oXmKa5q+dQwggEEBgNVHSUEgfww
# gfkGBysGAQUCAwUGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNxQCAQYJKwYB
# BAGCNxUGBgorBgEEAYI3CgMMBgkrBgEEAYI3FQYGCCsGAQUFBwMJBggrBgEFBQgC
# AgYKKwYBBAGCN0ABAQYLKwYBBAGCNwoDBAEGCisGAQQBgjcKAwQGCSsGAQQBgjcV
# BQYKKwYBBAGCNxQCAgYKKwYBBAGCNxQCAwYIKwYBBQUHAwMGCisGAQQBgjdbAQEG
# CisGAQQBgjdbAgEGCisGAQQBgjdbAwEGCisGAQQBgjdbBQEGCisGAQQBgjdbBAEG
# CisGAQQBgjdbBAIwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQD
# AgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUKV5RXmSuNLnrrJwN
# p4x1AdEJCygwggFoBgNVHR8EggFfMIIBWzCCAVegggFToIIBT4YxaHR0cDovL2Ny
# bC5taWNyb3NvZnQuY29tL3BraWluZnJhL2NybC9hbWVyb290LmNybIYjaHR0cDov
# L2NybDIuYW1lLmdibC9jcmwvYW1lcm9vdC5jcmyGI2h0dHA6Ly9jcmwzLmFtZS5n
# YmwvY3JsL2FtZXJvb3QuY3JshiNodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9hbWVy
# b290LmNybIaBqmxkYXA6Ly8vQ049YW1lcm9vdCxDTj1BTUVSb290LENOPUNEUCxD
# Tj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1
# cmF0aW9uLERDPUFNRSxEQz1HQkw/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9i
# YXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIBqwYIKwYBBQUH
# AQEEggGdMIIBmTBHBggrBgEFBQcwAoY7aHR0cDovL2NybC5taWNyb3NvZnQuY29t
# L3BraWluZnJhL2NlcnRzL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKG
# K2h0dHA6Ly9jcmwyLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYI
# KwYBBQUHMAKGK2h0dHA6Ly9jcmwzLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9v
# dC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0FNRVJv
# b3RfYW1lcm9vdC5jcnQwgaIGCCsGAQUFBzAChoGVbGRhcDovLy9DTj1hbWVyb290
# LENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
# Tj1Db25maWd1cmF0aW9uLERDPUFNRSxEQz1HQkw/Y0FDZXJ0aWZpY2F0ZT9iYXNl
# P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwDQYJKoZIhvcNAQEL
# BQADggIBAFAQI7dPD+jfXtGt3vJp2pyzA/HUu8hjKaRpM3opya5G3ocprRd7vdTH
# b8BDfRN+AD0YEmeDB5HKQoG6xHPI5TXuIi5sm/LeADbV3C2q0HQOygS/VT+m1W7a
# /752hMIn+L4ZuyxVeSBpfwf7oQ4YSZPh6+ngZvBHgfBaVz4O9/wcfw91QDZnTgK9
# zAh9yRKKls2bziPEnxeOZMVNaxyV0v152PY2xjqIafIkUjK6vY9LtVFjJXenVUAm
# n3WCPWNFC1YTIIHw/mD2cTfPy7QA1pT+GPARAKt0bKtq9aCd/Ym0b5tPbpgCiRtz
# yb7fbNS1dE740re0COE67YV2wbeo2sXixzvLftH8L7s9xv9wV+G22qyKt6lmKLjF
# K1yMw4Ni5fMabcgmzRvSjAcbqgp3tk4a8emaaH0rz8MuuIP+yrxtREPXSqL/C5bz
# MzsikuDW9xH10graZzSmPjilzpRfRdu20/9UQmC7eVPZ4j1WNa1oqPHfzET3ChIz
# J6Q9G3NPCB+7KwX0OQmKyv7IDimj8U/GlsHD1z+EF/fYMf8YXG15LamaOAohsw/y
# wO6SYSreVW+5Y0mzJutnBC9Cm9ozj1+/4kqksrlhZgR/CSxhFH3BTweH8gP2FEIS
# RtShDZbuYymynY1un+RyfiK9+iVTLdD1h/SxyxDpZMtimb4CgJQlMYIZ6DCCGeQC
# AQEwWDBBMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1F
# MRUwEwYDVQQDEwxBTUUgQ1MgQ0EgMDECEzYAAAIBHbrxII1Q4GgAAgAAAgEwDQYJ
# YIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYB
# BAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICz1spHJIHss
# z2VFUST5UpvuJLQBouWFhVjyMlXXq/LeMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBN
# AGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJ
# KoZIhvcNAQEBBQAEggEAr0Y7pAdUNvEMdv15wm3DvDDi3uW3VSfLlHlCTsBvKcSt
# GEvkol3a+FfN/3dxN3m5/kYy5bntP04rHS8oub8wNFIP9bogD23pZwS+vwOZ45Du
# l4IVyEE8wUCQRJGEIUaeEZwxwV0iLTLyukj9RXrSEAVcXonCn5Bmc06NPh0iX3yX
# HgjSHJRqB+PhFmjtOP8OToJJPJXcFTEA3UCyTD/Wpw/dJJWZ0CyCNe9/g/NP/OSO
# HYEq/DBco2bPBDYMgGR5wGNnlul8p0ymadbOxbmO7nIaNNC+/tztv4mn+vHB/WVl
# 7qlQjdw0KWlO988MHV31Wk/8+U3vVDywuFQ7SlV9SKGCF7AwghesBgorBgEEAYI3
# AwMBMYIXnDCCF5gGCSqGSIb3DQEHAqCCF4kwgheFAgEDMQ8wDQYJYIZIAWUDBAIB
# BQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGEWQoDATAx
# MA0GCWCGSAFlAwQCAQUABCA7zlZebMK9i5ki2Xu/PnRK4/4skiJaJli8d2XahLfA
# UwIGaBLHHwKPGBMyMDI1MDUwOTExMjIzNS43MDVaMASAAgH0oIHZpIHWMIHTMQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNy
# b3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGll
# bGQgVFNTIEVTTjo1OTFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgU2VydmljZaCCEf4wggcoMIIFEKADAgECAhMzAAAB9BdGhcDLPznl
# AAEAAAH0MA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy
# MDEwMB4XDTI0MDcyNTE4MzA1OVoXDTI1MTAyMjE4MzA1OVowgdMxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJ
# cmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1Mg
# RVNOOjU5MUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
# cCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApwhOE6bQ
# gC9qq4jJGX2A1yoObfk0qetQ8kkj+5m37WBxDlsZ5oJnjfzHspqPiOEVzZ2y2ygG
# gNZ3/xdZQN7f9A1Wp1Adh5qHXZZh3SBX8ABuc69Tb3cJ5KCZcXDsufwmXeCj81Ez
# JEIZquVdV8STlQueB/b1MIYt5RKis3uwzdlfSl0ckHbGzoO91YTKg6IExqKYojGr
# eCopnIKxOvkr5VZsj2f95Bb1LGEvuhBIm/C7JysvJvBZWNtrspzyXVnuo+kDEyZw
# pkphsR8Zvdi+s/pQiofmdbW1UqzWlqXQVgoYXbaYkEyaSh/heBtwj1tue+LcuOcH
# APgbwZvQLksKaK46oktregOR4e0icsGiAWR9IL+ny4mlCUNA84F7GEEWOEvibig7
# wsrTa6ZbzuMsyTi2Az4qPV3QRkFgxSbp4R4OEKnin8Jz4XLI1wXhBhIpMGfA3BT8
# 50nqamzSiD5L5px+VtfCi0MJTS2LDF1PaVZwlyVZIVjVHK8oh2HYG9T26FjR9/I8
# 5i5ExxmhHpxM2Z+UhJeZA6Lz452m/+xrA4xrdYas5cm7FUhy24rPLVH+Fy+ZywHA
# p9c9oWTrtjfIKqLIvYtgJc41Q8WxbZPR7B1uft8BFsvz2dOSLkxPDLcXWy16ANy7
# 3v0ipCxAwUEC9hssi0LdB8ThiNf/4A+RZ8sCAwEAAaOCAUkwggFFMB0GA1UdDgQW
# BBQrdGWhCtEsPid1LJzsTaLTKQbfmzAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJl
# pxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAx
# MCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3Rh
# bXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM
# MAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEA
# 3cHSDxJKUDsgacIfRX60ugODShsBqwtEURUbUXeDmYYSa5oFj34RujW3gOeCt/Ob
# DO45vfpnYG5OS5YowwsFw19giCI6JV+ccG/qqM08nxASbzwWtqtorzQiJh9upsE4
# TVZeKYXmbyx7WN9tdbVIrCelVj7P6ifMHTSLt6BmyoS2xlC2cfgKPPA13vS3euqU
# l6zwe7GAhjfjNXjKlE4SNWJvdqgrv0GURKjqmamNvhmSJane6TYzpdDCegq8adlG
# H85I1EWKmfERb1lzKy5OMO2e9IkAlvydpUun0C3sNEtp0ehliT0Sraq8jcYVDH4A
# 2C/MbLBIwikjwiFGQ4SlFLT2Tgb4GvvpcWVzBxwDo9IRBwpzngbyzbhh95UVOrQL
# 2rbWHrHDSE3dgdL2yuaHRgY7HYYLs5Lts30wU9Ouh8N54RUta6GFZFx5A4uITgyJ
# cVdWVaN0qjs0eEjwEyNUv0cRLuHWJBejkMe3qRAhvCjnhro7DGRWaIldyfzZqln6
# FsnLQ3bl+ZvVJWTYJuL+IZLI2Si3IrIRfjccn29X2BX/vz2KcYubIjK6XfYvrZQN
# 4XKbnvSqBNAwIPY2xJeB4o9PDEFI2rcPaLUyz5IV7JP3JRpgg3xsUqvFHlSG6uMI
# WjwH0GQIIwrC2zRy+lNZsOKnruyyHMQTP7jy5U92qEEwggdxMIIFWaADAgECAhMz
# AAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9v
# dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0z
# MDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP9
# 7pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMM
# tY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gm
# U3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130
# /o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP
# 3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7
# vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+A
# utuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz
# 1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6
# EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/Zc
# UlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZy
# acaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJ
# KwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVd
# AF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8G
# CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv
# UmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQC
# BAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYD
# VR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZF
# aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9v
# Q2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcw
# AoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJB
# dXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cB
# MSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7
# bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/
# SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2
# EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2Fz
# Lixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0
# /fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9
# swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJ
# Xk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+
# pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW
# 4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N
# 7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDWTCCAkECAQEwggEBoYHZpIHWMIHTMQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNy
# b3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGll
# bGQgVFNTIEVTTjo1OTFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAv+LZ/Vg0s17Xek4iG9R9
# c/7+AI6ggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkq
# hkiG9w0BAQsFAAIFAOvH0RkwIhgPMjAyNTA1MDkwMDU1NTNaGA8yMDI1MDUxMDAw
# NTU1M1owdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA68fRGQIBADAKAgEAAgIc0gIB
# /zAHAgEAAgISrjAKAgUA68kimQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE
# AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IB
# AQAZcdzwlPxHmebHEDOtmU+XW+v89sUogl2Jc2PnkWkW9qycJ01AoHmhHEg9/ChV
# 6XITemtV4JcwReNMsRvi4fnGSJHYuUaafXrMVHNN+eXv9WbReIKh+T8Ka5pIAs/u
# X80bzW2aF7NgkBL9D/t1/6GKYhSfnOUBcuISdUzVxEc/l+X3LZBD27XSWBoqSAbF
# QDkrVviuhWrKyjmmh38vjSnekpNcc9zvTr/afu4fLyfsx0dw9E0DWkEA6OAOWPEH
# vkwMLpoEji3fLkn6T1thk2Kkv3lzOj0q7Ku6iOy7oqxkc9Saz0ZTuXc9vaDtL4eb
# l+urIh7JgqFipQitSUtuwHR4MYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgUENBIDIwMTACEzMAAAH0F0aFwMs/OeUAAQAAAfQwDQYJYIZIAWUDBAIB
# BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx
# IgQgWbV7EB0+Atp+6FitI9UvaeBuDOEH8gbYqrk95+DMBJcwgfoGCyqGSIb3DQEJ
# EAIvMYHqMIHnMIHkMIG9BCA/WMJ8biaT6njvkknB8Q7hSQIi8ys6vIBvZg60RBjW
# azCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB9BdG
# hcDLPznlAAEAAAH0MCIEIMPHCKRaiMwm6D8jABkbcf911aJcBf+EG6C+JEcHOArg
# MA0GCSqGSIb3DQEBCwUABIICAI+D4ZFxHKLA+YcIqRYSysEomldYELricdf4Vhrn
# hdKmNYSSVsYUZcL70GC+s+D23AwEVntnY73wCRuCXFNNqCd9TnOTXxAEOEd7Ycyc
# i2xFrtKpHWCjr+KNqSC4ZDEBaGRnc0kx5kXTpXsekN4FbJbgaLNP0UMcPgDa4rmB
# uhKbl3vyTJdYJ7j9Ob79snAHVmJcPZNFNOWCHf8H7iOLG7W8B2KN2jSmUjPbBsqr
# HxLpp8FtmT52Kxt3t9LNuDGJvSYEbiqT8ajVzWYdLZS0jK6+PF4KungnPxysP5IU
# FqSs8LfaBONIiI4ki8Xaci5mnuArC1EMMfmnNAk6/Lze9qtTjZFTXT0PN8LlbM5u
# KqGbyWa77gC8vQnuvvBCec0IoPRqUeCB8JNhjiVMT6oFhULXVQtdWmmlB5WNjvpU
# fHerRhCe5tvhR2kXAS6QygMlTfv599Y37Kwgw8WbkyJ9wwiNLIrKCA0cDgVwKuSz
# OT8ODLWln3ZZkzcitNA02Cngob3XL+HVax/R4d/yxOq5GDtuomNmcJWUq7gXIzxl
# wzafoNJQpFU2PoC+oU9f6QqFUwWURbC5QLQ3+JG2jsqS4ENIr6yC12QDNDvTsTes
# OwZRuuypKuyOYzgBzR/3Ni/kj8M8akeGxcsxCoB9m50tDNZU7E5wnJVHeq/AGqlL
# x8JZ
# SIG # End signature block
