$TIMEOUT = 3
$ErrorActionPreference = "Stop"


function WaitForSharePointTimerJobToFinish([Microsoft.SharePoint.Administration.SPJobDefinition] $job)
{
    If ($job -eq $null)
    {
        return
    }
    
    $jobName = $job.Name
    Write-Host -NoNewLine ("Waiting for SharePoint timer job ($jobName) to finish...")
    
    While ((Get-SPTimerJob $jobName -Debug:$false) -ne $null) 
    {
        Write-Host -NoNewLine "."
        Start-Sleep -Seconds 5
    }
    
	Write-Host

    Write-Host "The SharePoint timer job ($jobName) has finished."
}

function WaitForSolutionDeploymentJobsToFinish([string] $solutionName)
{
    Write-Debug "solutionName: $solutionName"

    If ([string]::IsNullOrEmpty($solutionName) -eq $true)
    {
        Write-Debug "Waiting for all solution deployment jobs to finish..."
        $jobNameFilter = "*solution-deployment*"
    }
    Else
    {
        Write-Debug ("Waiting for solution deployment ($solutionName) to finish...")
        $jobNameFilter = "*solution-deployment*$solutionName*"
    }
    
    Write-Debug "jobNameFilter: $jobNameFilter"
    
    $jobs = Get-SPTimerJob -Debug:$false  | Where { $_.Name -like $jobNameFilter }
    
    If ($jobs -eq $null)
    {
        Write-Debug "No solution deployment jobs found"
        return
    }
    
    If ($jobs -is [Array])
    {
        Foreach ($job in $jobs)
        {
            WaitForSharePointTimerJobToFinish $job
        }
    }
    Else
    {
        WaitForSharePointTimerJobToFinish $jobs
    }
}

function CallUninstallSolutionByName($solutionName) {
    $solution = Get-SPSolution $solutionName -ErrorAction:SilentlyContinue
    if($solution)
    {    
        if($solution.Deployed -eq $true)
        {   
		 	if ($solution.ContainsWebApplicationResource -eq $false) {
            	Uninstall-SPSolution $solution -Confirm:$false
		 	}
		 	else {
				Uninstall-SPSolution $solution -Confirm:$false  -AllWebApplications 		 		
		 	}
        }
    }
}

function WaitUntilDeployed($solutionName) {
	Write-Host -NoNewLine "Waiting for solution ($solutionName) is canceled deploy ..."
    while($(Get-SPSolution $solutionName).Deployed -eq $true) # Ждем, пока не произойдет uninstall
    {                         
		Write-Host -NoNewLine "."
        Start-Sleep -Seconds 5
    }
	Write-Host
}

function WaitUntilSandboxDeployed($solutionName, $webUrl) {
	Write-Host -NoNewLine "Waiting for sandboxed solution ($solutionName) is canceled deploy ..."
    while($(Get-SPUserSolution $solutionName -Site:$webUrl).Deployed -eq $true) # Ждем, пока не произойдет uninstall
    {                         
		Write-Host -NoNewLine "."
        Start-Sleep -Seconds 5
    }
	Write-Host
}


function UninstallAndRemoveSolutionByName($solutionName) {
 	Write-Host "$solutionName..." -ForegroundColor Yellow

    $solution = Get-SPSolution $solutionName -ErrorAction:SilentlyContinue
        	
    if($solution)
    {    
		CallUninstallSolutionByName $solutionName

		WaitUntilDeployed $solutionName
		WaitForSolutionDeploymentJobsToFinish $solutionName

		Remove-SPSolution $solution -Confirm:$false;            
    }
}

function AddAndInstallSolutionByName($solutionName, $solutionDirectory, $siteUrl, $reInstall) {               
    Write-Host -NoNewLine "$solutionName..." -ForegroundColor Yellow
    $fullPathToSolution = $solutionDirectory + "\" + $solutionName
	
	$solution = Get-SPSolution | where {$_.Name -eq $solutionName }
	if ($solution -ne $null){
		if ($reInstall){
			UninstallAndRemoveSolutionByName $solutionName
			Add-SPSolution -LiteralPath $fullPathToSolution -ErrorAction: Stop
		}
		elseif ($solution.Deployed -ne $false){
			Write-Host "was skipped because ReInstall flage is False or not set"
			return
		}
	}
	else {
		$solution = Add-SPSolution -LiteralPath $fullPathToSolution -ErrorAction: Stop
	}
    if ($solution.ContainsWebApplicationResource -eq $false) 
    {
      Install-SPSolution $solution -GACDeployment -Force -ErrorAction: Stop
    } 
    else
    {
      $site = New-Object -Type Microsoft.SharePoint.SPSite -ArgumentList $siteUrl	  
      Install-SPSolution $solution -GACDeployment -WebApplication $site.WebApplication -Force -ErrorAction: Stop
    }    
   
    $secs = 0
    while($solution.Deployed -eq $false)
    {
	    Write-Host -NoNewLine "."
        Start-Sleep -Seconds 5
    }
	Write-Host
}


function UninstallAndRemoveSandboxedSolutionByName($solutionName, $webUrl) {
 	Write-Host "$solutionName..." -ForegroundColor Yellow

    $solution = Get-SPUserSolution $solutionName -ErrorAction:SilentlyContinue -Site:$webUrl
        	
    if($solution)
    {    
		if ($solution.Status -eq "Activated")
		{
			Uninstall-SPUserSolution $solution -Confirm:$false -Site:$webUrl
		}	

		#CallUninstallSolutionByName $solutionName

		WaitUntilSandboxDeployed $solutionName $webUrl
		
		#WaitForSolutionDeploymentJobsToFinish $solutionName

		Remove-SPUserSolution $solutionName -Confirm:$false -Site:$webUrl
    }
}


function AddAndInstallSPUserSolutionByName($solutionName, $solutionDirectory, $siteUrl, $reInstall) {               
    Write-Host "$solutionName..." -ForegroundColor Yellow	
    $fullPathToSolution = $solutionDirectory + "\" + $solutionName
	
	$solution = Get-SPUserSolution -Site $siteUrl | where {$_.Name -eq $solutionName } -ErrorAction: Stop
	if ($solution -ne $null){
		if ($reInstall){
			UninstallAndRemoveSandboxedSolutionByName $solutionName $siteUrl
			Add-SPUserSolution -LiteralPath $fullPathToSolution -Site $siteUrl -ErrorAction: Stop
		}
		elseif ($solution.Status -ne "Activated"){
			Write-Host "was skipped because ReInstall flage is False or not set"
			return
		}
	}
	else {
		$solution = Add-SPUserSolution -LiteralPath $fullPathToSolution -Site $siteUrl -ErrorAction: Stop
	}
	
	#Write-Host "Install-SPUserSolution ..."
    Install-SPUserSolution -Identity $solutionName -Site $siteUrl >$null
	
	$solution = Get-SPUserSolution $solutionName -Site $siteUrl -ErrorAction: Stop 
    $secs = 0
    while($solution.Status -ne "Activated")
    {
	    Write-Host -NoNewLine "."
        Start-Sleep -Seconds 5
    }
	Write-Host	
}

function IsSolutionDeployed($solutionName, $sandboxed, $siteUrl){
	try {
		if ($sandboxed){
			$solution = Get-SPUserSolution -site $siteUrl | Where { ($solutionName -eq $_.Name) }  -ErrorAction  'Stop'
			if($solution.Status -eq "Activated") { return $true }
			else { return $false }
		}
		else{
			$solution = Get-SPSolution $SolutionName -ErrorAction 'Stop'
			return $solution.Deployed
		}
	}
	catch {
		return $false
	}
}