# Copyright (c) 2018-2020 "Graph Foundation,"
# Graph Foundation, Inc. [https://graphfoundation.org]
#
# This file is part of ONgDB.
#
# ONgDB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Copyright (c) 2002-2018 "Neo4j,"
# Neo4j Sweden AB [http://neo4j.com]
#
# This file is part of Neo4j.
#
# Neo4j is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


<#
.SYNOPSIS
Invokes various ONgDB Utilities

.DESCRIPTION
Invokes various ONgDB Utilities.  This is a generic utility function called by the external functions e.g. Shell, Import

.PARAMETER Command
A string of the command to run.

.PARAMETER CommandArgs
Command line arguments to pass to the utility

.OUTPUTS
System.Int32
0 = Success
non-zero = an error occured

.NOTES
Only supported on version 1.x ONgDB Community and Enterprise Edition databases

.NOTES
This function is private to the powershell module

#>
function Invoke-ONgDBUtility
{
  [CmdletBinding(SupportsShouldProcess = $false,ConfirmImpact = 'Low')]
  param(
    [Parameter(Mandatory = $false,ValueFromPipeline = $false,Position = 0)]
    [string]$Command = ''

    ,[Parameter(Mandatory = $false,ValueFromRemainingArguments = $true)]
    [object[]]$CommandArgs = @()
  )

  begin
  {
  }

  process
  {
    # Determine the ONgDB Home Directory.  Uses the ONGDB_HOME environment variable or a parent directory of this script
    $ONgDBHome = Get-ONgDBEnv 'ONGDB_HOME'
    if (($ONgDBHome -eq $null) -or (-not (Test-Path -Path $ONgDBHome))) {
      $ONgDBHome = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
    }
    if ($ONgDBHome -eq $null) { throw "Could not determine the ONgDB home Directory.  Set the ONGDB_HOME environment variable and retry" }
    Write-Verbose "ONgDB Root is '$ONgDBHome'"

    $thisServer = Get-ONgDBServer -ONgDBHome $ONgDBHome -ErrorAction Stop
    if ($thisServer -eq $null) { throw "Unable to determine the ONgDB Server installation information" }
    Write-Verbose "ONgDB Server Type is '$($thisServer.ServerType)'"
    Write-Verbose "ONgDB Version is '$($thisServer.ServerVersion)'"
    Write-Verbose "ONgDB Database Mode is '$($thisServer.DatabaseMode)'"

    $GetJavaParams = @{}
    switch ($Command.Trim().ToLower())
    {
      "shell" {
        Write-Verbose "Shell command specified"
        $GetJavaParams = @{
          StartingClass = 'org.neo4j.shell.StartClient';
        }
        break
      }
      "admintool" {
        Write-Verbose "Admintool command specified"
        $GetJavaParams = @{
          StartingClass = 'org.neo4j.commandline.admin.AdminTool';
        }
        break
      }
      "import" {
        Write-Verbose "Import command specified"
        $GetJavaParams = @{
          StartingClass = 'org.neo4j.tooling.ImportTool';
        }
        break
      }
      "backup" {
        Write-Verbose "Backup command specified"
        if ($thisServer.ServerType -ne 'Enterprise')
        {
          throw "ONgDB Server type $($thisServer.ServerType) does not support online backup"
        }
        $GetJavaParams = @{
          StartingClass = 'org.neo4j.backup.BackupTool';
        }
        break
      }
      default {
        Write-Host "Unknown utility $Command"
        return 255
      }
    }

    # Generate the required Java invocation
    $JavaCMD = Get-Java -ONgDBServer $thisServer -ForUtility @GetJavaParams
    if ($JavaCMD -eq $null) { throw 'Unable to locate Java' }

    $ShellArgs = $JavaCMD.args
    if ($ShellArgs -eq $null) { $ShellArgs = @() }

    # Parameters need to be wrapped in double quotes to avoid issues in case they contain spaces.
    # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-7#parameters
    # https://github.com/PowerShell/PowerShell/issues/5576
    foreach ($CmdArg in $CommandArgs) {
      if ($CmdArg -match '^".*"$' -or $CmdArg -match "^'.*'$") {
        $ShellArgs += $CmdArg
      } else {
        $ShellArgs += "`"$CmdArg`""
      }
    }

    Write-Verbose "Starting ongdb utility using command line $($JavaCMD.java) $ShellArgs"
    $result = (Start-Process -FilePath $JavaCMD.java -ArgumentList $ShellArgs -Wait -NoNewWindow -Passthru)
    return $result.exitCode
  }

  end
  {
  }
}
