<#
.SYNOPSIS
    Update HES
.DESCRIPTION
    HES Server Update script
.PARAMETER service
    Default HES
    Name of IIS site
.PARAMETER debug
    Default 0
    if 1, then writing to the temporary log file is performed
.PARAMETER url
    Default ""
    url to download the update file.
    Useful for offline updates. In this case, you should specify file://<path to the update zip file>
    for example  update -url file://C:/Updates/windows_x64_latest.zip
    if "", then url  will be taken from https://update.hideez.com/hes/build.json
.PARAMETER urlLogin
    Default ""
    if the update url requires access by login, password, then you can specify the login here
.PARAMETER urlPassword
    Default ""
    if the update url requires access by login, password, then you can specify the password here
#>

Param (
    $service="HES",
    $debug=0,
    $url="",
    $urlLogin="",
    $urlPassword=""

)

if ($debug -eq 1 ) {
    Write-Host "service = $service"
    Write-Host "url = $url"
}

## addinng Web-Scripting-Tools
$required_toolls=get-windowsfeature|where{$_.name -eq "Web-Scripting-Tools"  -and $_.Installstate -ne "Installed" } 
if ($required_toolls)
{
    Write-Host "adding Web-Scripting-Tools Feature ..."
    Add-WindowsFeature Web-Scripting-Tools
}

# when debuggging, enable log file
if ($debug -eq 1)
{
    $logfie = New-TemporaryFile
    Start-Transcript -Append  $logfie.FullName
}


Function Get_MySql_Credenshels{
    $info = "" | Select-Object -Property DATABASE_HOST,DATABASE_PORT,DATABASE_NAME,DATABASE_USER,DATABASE_PASSWORD
    $CONNECTIONSTRING  -split ';' | ForEach-Object -Process  {
        $key, $value = $_ -split '='

        if ($key -eq 'server') 
        {
            $info.DATABASE_HOST = $value
        }
        if ($key -eq 'port') 
        {
            $info.DATABASE_PORT = $value
        }

        if ($key -eq 'database') 
        {
            $info.DATABASE_NAME = $value
        }
        if ($key -eq 'uid') 
        {
            $info.DATABASE_USER = $value
        }
        if ($key -eq 'pwd') 
        {
            $info.DATABASE_PASSWORD = $value
        }
    }
    Return $info
}

Function Get_MsSql_Credenshels{
    # Write-Host "CONNECTIONSTRING = $CONNECTIONSTRING"

    $info = "" | Select-Object -Property DATABASE_HOST,DATABASE_PORT,DATABASE_NAME,DATABASE_USER,DATABASE_PASSWORD
    $CONNECTIONSTRING  -split ';' | ForEach-Object -Process {
        $key, $value = $_ -split '='
        #Write-Host "key = $key"
        if ($key.ToUpper() -eq 'SERVER') 
        {
            $hostport =  $value -split ',' 
            #$global:DATABASE_HOST = $hostport[0]
            $info.DATABASE_HOST =  $hostport[0]
            #Write-Host "global:DATABASE_HOST = $global:DATABASE_HOST"
            #$global:DATABASE_PORT = $hostport[1]
            $info.DATABASE_PORT =  $hostport[1]
        }
        if ($key -eq 'Initial Catalog') 
        {
            #$global:DATABASE_NAME = $value
            $info.DATABASE_NAME = $value
        }
        if ($key -eq 'User ID') 
        {
            #$global:DATABASE_USER = $value
            $info.DATABASE_USER = $value
        }
        if ($key -eq 'Password') 
        {
            #$global:DATABASE_PASSWORD = $value
            $info.DATABASE_PASSWORD = $value
        }
    }

    Return $info
}




Function Stop_HES{

    # get the name of appPool

    $NAME_OFAppPool=$site.Applications[0].ApplicationPoolName

    # stopping site
    Set-Location $env:windir\System32\inetsrv
    .\appcmd.exe  stop site /site.name:$service

    if ($?)
    {
        #echo "$service stopped"
    }

    else
    {
    write-host "Error stopping server with name  $service !"
    exit 1
    }

    # closing open sessions (if any)
    gwmi -NS 'root\WebAdministration' -class 'WorkerProcess'  |   where -Property AppPoolName -eq $NAME_OFAppPool  |   select AppPoolName,ProcessId  |  Stop-Process -Id   {$_.ProcessId} -Force
    Write-Host "waiting for 10 seconds to complete the sessions..."
    Wait-Event -Timeout 10
}


Function Start_HES{
    # startiing  service
    Set-Location $env:windir\System32\inetsrv 
    .\appcmd.exe  start site /site.name:$service
}


Function Restore_HES{
    Rename-Item  -force -Path $BACKUP_HES_DIR -NewName $HES_DIR
    Start_HES 
}



$site = Get-IISSite -Name $service
#HES dir
$HES_DIR = $site| Foreach-Object {$_.Applications} | Foreach-Object {$_.VirtualDirectories} | Foreach-Object {$_.PhysicalPath}
$CURRENT_FOLDER = (Get-Location).Path

#$HES_DIR  = Split-Path -Path $pscommandpath

#for create backup of database, parsing json file
$JSON_FILE=$HES_DIR+"\appsettings.Production.json"

$JSON=Get-Content $JSON_FILE | ConvertFrom-Json
$CONNECTIONSTRING=$JSON.ConnectionStrings.DefaultConnection
$PROVIDER=$JSON.ConnectionStrings.Provider

if ($null -eq  $PROVIDER )
    { $PROVIDER="MySql"} 

if ($url -eq "") {
    $JSON_URL = "https://update.hideez.com/hes/build.json"
    $response = Invoke-WebRequest -Uri $JSON_URL
    $json = ConvertFrom-Json -InputObject $response.Content
    $url=$json.win
}


#Write-Host "JSON = $JSON"
Write-Host "PROVIDER = $PROVIDER"

if ($PROVIDER -eq "MySql") {
    $ConnectInfo = Get_MySql_Credenshels
}

if ($PROVIDER -eq "MsSql") {
    $ConnectInfo = Get_MsSql_Credenshels
}


 $DATABASE_HOST = $ConnectInfo.DATABASE_HOST
 $DATABASE_PORT = $ConnectInfo.DATABASE_PORT
 $DATABASE_NAME = $ConnectInfo.DATABASE_NAME
 $DATABASE_USER = $ConnectInfo.DATABASE_USER
 $DATABASE_PASSWORD = $ConnectInfo.DATABASE_PASSWORD

 if ($debug -eq 1 ) {
    write-host "HES_DIR = $HES_DIR"
    write-host "HESSERVICE = $service"
    write-host "URL = $url"

    write-host "JSON_FILE = $JSON_FILE"
    write-host "DATABASE_HOST = $DATABASE_HOST"
    write-host "DATABASE_PORT = $DATABASE_PORT"
    write-host "DATABASE = $DATABASE_NAME"
    write-host "DATABASE_PASSWORD = $DATABASE_PASSWORD"
}




Stop_HES


# rename old HES dir
$BACKUP_HES_DIR = $HES_DIR + "-" + (Get-Date -Format "yyyy-MM-dd-HH-mm-ss") + ".Old"
Rename-Item  -force -Path $HES_DIR -NewName $BACKUP_HES_DIR
if ($?)
{
    echo "Create backup of $HES_DIR"
}
else
{
   echo "Error Create of backup of $HES_DIR!"
   Start_HES
   exit 1
}


Function MySqlBackup {

$MYSQL_HOME='C:\Program Files\MySQL\MySQL Server 8.0'
Set-Location "$MYSQL_HOME\bin"
# create temp file with password 
$tmpfie = New-TemporaryFile
Add-Content -path $tmpfie.FullName @"
[client]
password = "$DATABASE_PASSWORD"

[mysqldump]
user = "$DATABASE_USER"
host = "$DATABASE_HOST"
port = "$DATABASE_PORT"
password = "$DATABASE_PASSWORD"
"@

# create dump of database
.\mysqldump.exe  --defaults-extra-file=$tmpfie --result-file=$BACKUP_HES_DIR\$DATABASE_NAME.sql --no-tablespaces $DATABASE_NAME

if ($?)
{
    
    Write-Output "dump created successfully"
    Remove-Item $tmpfie.FullName
}
else
{
    Write-Output 'Failure create dump of database!'
    Write-Output "An error occurred. Update failed..."
    Remove-Item $tmpfie.FullName
    exit 1
}


#  altenative is  (but error code <> 0)
# .\mysqldump.exe -u "$DATABASE_USER" -p"$DATABASE_PASSWORD" --result-file="$BACKUP_HES_DIR"\"$DATABASE_NAME".sql --databases "$DATABASE_NAME"

}


Function MsSqlBackup {

    #write-host "DATABASE = $DATABASE_NAME"
    sqlcmd -S $DATABASE_HOST,$DATABASE_PORT -U $DATABASE_USER  -P $DATABASE_PASSWORD -Q "BACKUP DATABASE [$DATABASE_NAME] TO DISK = N'$BACKUP_HES_DIR\$DATABASE_NAME.bak' WITH NOFORMAT, NOINIT, NAME = 'db-full', SKIP, NOREWIND, NOUNLOAD, STATS = 10"
    # Backup-SqlDatabase -ServerInstance "." -Database $DATABASE_NAME -BackupFile "$BACKUP_HES_DIR\$DATABASE_NAME.bak"

    if ($?)
    {
        Write-Output "dump created successfully"
    }
    else
    {
        Write-Output 'Failure create dump of database!'
        Restore_HES
        Write-Output "An error occurred. Update failed..."
        exit 1
    }

}

if ($PROVIDER -eq "MySql" )
    { MySqlBackup} 

if ($PROVIDER -eq "MsSql" )
    { MsSqlBackup} 

try {

    # download and extract binares
    $TempDir = [System.IO.Path]::GetTempPath()
    #write-host "TempDir = $TempDir"

    $localzipfile = $TempDir+"\hes.zip"
    if (Test-Path $localzipfile) {
        Remove-Item $localzipfile
    }
  
    $ProgressPreference = 'SilentlyContinue'
    Write-Host "Downloading HES ..."
    $urlCredential = $null

    if ($urlPassword -ne "") {
        write-host "access to the update is carried out with a login and password..."
        $secUrlPassword = ConvertTo-SecureString $urlPassword -AsPlainText -Force
        $urlCredential = New-Object System.Management.Automation.PSCredential($urlLogin, $secUrlPassword)
    }

    Invoke-WebRequest -Uri  $url  -OutFile $localzipfile -Credential $urlCredential
    Write-Host "install HES ..."
    Expand-Archive -LiteralPath $localzipfile -DestinationPath $HES_DIR -Force
    Remove-Item $localzipfile

}
catch {
    Write-Host $_.Exception.Message -ForegroundColor Red
    Restore_HES
    Write-Output "An error occurred. Update failed..."
    exit 1
}



# copying an old json file 
$JSON=$HES_DIR+"\appsettings.Production.json"
$BACKUP_JSON=$BACKUP_HES_DIR+"\appsettings.Production.json"
Copy-Item -Path $BACKUP_JSON -Destination $JSON

# copying old update.ps1 file 
#$UPDATE=$HES_DIR+"\update.ps1"
#$BACKUP_UPDATE=$BACKUP_HES_DIR+"\update.ps1"
#Copy-Item -Path $BACKUP_UPDATE -Destination $UPDATE

Start_HES

#that's all ..
write-host "Finish"

if ($debug -eq 1)
{
    Stop-Transcript
    cat $logfie.FullName
}
Set-Location $CURRENT_FOLDER
