# -----------------------------------------------
# Параметры
# -----------------------------------------------
param(
        [Parameter(Mandatory=$True)]$ConfigurationFile, # конфигурационный файл
        [Parameter(Mandatory=$True)]$PortalUrl, # адрес портала
		[switch]
		$NonCheckRequirements,
		[switch]
		$FullErrorInformationInConsole
      )


 if ($ConfigurationFile -eq $null)
 {   
       throw "Не задан файл конфигурации"
 } 

# -----------------------------------------------
# Включаем логирование
# -----------------------------------------------
try{ Start-Transcript Install.log }
catch{}

# -----------------------------------------------
# Задаем CultureInfo
# -----------------------------------------------
try{
 [System.Threading.Thread]::CurrentThread.CurrentUICulture = [System.Globalization.CultureInfo]'ru-RU'
 [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]'ru-RU'
}
catch [Exception] {
    Write-Host $_.Exception.Message
    exit 1
}

# -----------------------------------------------
# Подключаем оснастку SharePoint
# -----------------------------------------------
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SharePoint')
$snap = Get-PSSnapin | Where-Object { $_.Name -eq "Microsoft.SharePoint.Powershell" }
if ($snap -eq $null)
{
    Add-PSSnapin "Microsoft.SharePoint.Powershell"
}

# -----------------------------------------------
# Подключаем наши библиотеки и модули
# -----------------------------------------------
$execFolder = $(Split-Path -Path $MyInvocation.MyCommand.Definition -Parent)
. $("$execFolder\ConfigurationSites.ps1")
. $("$execFolder\ConfigurationSecurityGroup.ps1")
. $("$execFolder\CreateCalendarOverlays.ps1")
. $("$execFolder\WebService.ps1")
. $("$execFolder\SolutionService.ps1")
. $("$execFolder\FeatureService.ps1")
. $("$execFolder\NavigationService.ps1")
. $("$execFolder\SecurityService.ps1")
. $("$execFolder\ExportImportService.ps1")
. $("$execFolder\RemoveTopNavigation.ps1")
. $("$execFolder\BuildTopNavigation.ps1")
. $("$execFolder\WebConfigService.ps1")
. $("$execFolder\CheckEnvironmentForInstallTypical.ps1")


try {
	Import-Module "$execFolder\SDC.Typical.PowerShell.dll" -ErrorAction Stop
}
catch {
    Write-Host "Предупреждение: Не удалось подгрузить библиотеку SDC.Typical.PowerShell.dll";
	Write-Host $_.Exception.GetType().FullName; 
	Write-Host $_.Exception.Message; 
}

# -----------------------------------------------
# Функция получения значения параметра из переменной окружения или из конфигурационного файла
# Вообще, для параметров, приоритет следующий: 1. Командная строка 2. Переменная окружения, 3. Конфигурационный файл
# -----------------------------------------------
function GetParamValue()
{
    param ([string]$paramName, $defaultValue)

    $result = $null

    # Ищем в переменных окружения
    $result = [environment]::GetEnvironmentVariable($paramName,"User")

    if($result -eq $null)
    {
        # Ищем в файле конфигурации
        if($Configuration.Parameters)
        {
            foreach($parameter in  $Configuration.Parameters.Parameter)
            {
                if($paramName -eq $parameter.Name)
                {
                   $result =  $parameter.Value
                   break
                }
            }       
        }
    }
               
    return $result
}

# -----------------------------------------------
# Функции для установке решений и активации возможностей
# -----------------------------------------------

function CheckSPEditionFeatureReq()
{
	param ($features, $feature)
	if($feature -eq $null -or $feature.Editions -eq $null) { return $true }
    if($feature.Editions.ChildNodes.Count -eq 0) { return $True }

	foreach ($edition in $feature.Editions.ChildNodes)
    {
		if($edition.Name -eq $installedVersion.Replace(' ', ''))
		{
			return $True;
		}
	}
	$comment = $features.'#comment'[$features.Feature.IndexOf($feature)]
	Write-Host ('Пропущена активация возможности: "'+$comment+'", так как для её активации требуется другая редакция SharePoint') -ForegroundColor Yellow
	return $False
}

function AddAndInstallSolutions()
{ 
    param ($Solutions)

    foreach ($solution in $Solutions.Solution)
    {
		$isSandboxed = $solution.Sandboxed -and [System.Convert]::ToBoolean($solution.Sandboxed)
		$isSkipIfDeployed = $solution.SkipIfDeployed -and [System.Convert]::ToBoolean($solution.SkipIfDeployed)
		$isReInstall = $solution.ReInstall -and [System.Convert]::ToBoolean($solution.ReInstall)
		$isSolutionDeployed = IsSolutionDeployed $solution.Name $isSandboxed $PortalUrl
		
		if ($isSolutionDeployed -and $isSkipIfDeployed)
		{
			continue;
		}
		
        if($isSandboxed)
        {
            AddAndInstallSPUserSolutionByName $solution.Name $ConfigurationFolder $PortalUrl $isReInstall
        }
        else
        {
            AddAndInstallSolutionByName $solution.Name $ConfigurationFolder $PortalUrl $isReInstall
        }
    }
}

function ActivateWebFeatures()
{
    param ($Features, $WebUrl)

    foreach ($feature in $Features.Feature)
    { 
		if(CheckSPEditionFeatureReq $Features $feature)
		{
			ActivateWebFeatureByWebUrlAndFeatureId $WebUrl $feature.ID
		}
    }
}

function ActivateSiteCollectionFeatures()
{
    param($Features, $SiteUrl)

    foreach ($feature in $Features.Feature)
    { 
		if(CheckSPEditionFeatureReq $Features $feature)
		{
			ActivateSiteFeatureBySiteUrlAndFeatureId $SiteUrl $feature.ID
		}
	}
}

function ActivateWebApplicationFeatures()
{
    param($Features)

    foreach ($feature in $Features.Feature)
    { 
		if(CheckSPEditionFeatureReq $Features $feature)
		{
			ActivateWebApplicationFeatureByWebUrlAndFeatureId $PortalUrl $feature.ID
		}
    }
}

# -----------------------------------------------
# Функция конфигурации сайтов
# -----------------------------------------------
function ConfigurationSites()
{ 
    param($BaseUrl, $Sites, $IsFirstLevelSite)

    foreach ($site in $Sites.Site)
    {
        Write-Host $site.Name -ForegroundColor: Green
            
        if($site.TypeRef)
        {            
            if($dictSiteTypeInfo.ContainsKey($site.TypeRef))
            {                                
               $siteTypeInfo =  $dictSiteTypeInfo[$site.TypeRef]
               $resultSiteInfo = New-SiteInfo -Url: $site.Url -Title: $site.Name  -ShouldExistXml: $site.ShouldExist -Template: $siteTypeInfo.Template -AddToTopNav: $false -ArrayOfSiteTypeFeaturesXml: $siteTypeInfo.Features -ArrayOfFeaturesXml: $site.Features.Feature -ArrayOfSiteTypeCalendarOverlaysXml: $siteTypeInfo.CalendarOverlays -ArrayOfSiteCalendarOverlaysXml: $site.CalendarOverlays.CalendarOverlay -ArrayOfSecurityGroupXml: $site.Security.Groups -PropertiesSiteXml: $site.Properties -PropertiesSiteTypeXml: $siteTypeInfo.Properties -ThemeSettings: $site.ThemeSettings
            }
            else
            {
                 throw  "Не найдено описание типа " + $site.TypeRef
            }
        }
        else
        {                
            $resultSiteInfo = New-SiteInfo -Url: $site.Url -Title: $site.Name -ShouldExistXml: $site.ShouldExist -Template: $site.Template -AddToTopNav: $false -ArrayOfFeaturesXml: $site.Features.Feature -ArrayOfSiteCalendarOverlaysXml: $site.CalendarOverlays.CalendarOverlay -ArrayOfSecurityGroupXml: $site.Security.Groups -PropertiesSiteXml: $site.Properties -ThemeSettings: $site.ThemeSettings
        }

        ConfigurationSiteBySiteInfo -SiteInfo: $resultSiteInfo -BaseUrl: $BaseUrl

        # Дочение сайты
        if ($site.Site -or $site.Site.Count -gt 0)
        {            
            if($site.Url -eq "/") # Корневой сайт
            {
                ConfigurationSites -BaseUrl: "$($BaseUrl)" -Sites: $site -IsFirstLevelSite: $true   
            }
            else
            {
                ConfigurationSites -BaseUrl: "$($BaseUrl)/$($site.Url)" -Sites: $site -IsFirstLevelSite: $false   
            }
            
        }
    }
}

function DisableMinimalDownload()
{
	param ($PortalUrl)
	$web = Get-SPWeb -Identity $PortalUrl
	if ($web.EnableMinimalDownload) {
		Write-Host $web.Url отключено -ForegroundColor: Green
		Disable-SPFeature –Url $PortalUrl –Identity “MDSFeature” -Confirm:$false
	}
	# Тоже самое для всех дочерних
	$subwebs = $web.GetSubwebsForCurrentUser()
	foreach($subweb in $subwebs) {DisableMinimalDownload -PortalUrl: $subweb.Url }
}
# -----------------------------------------------
# Функция импорта данных
# -----------------------------------------------
function ImportData()
{
    param($ImportedData)

    foreach ($data in $ImportedData.Data)
    { 
        $importedDataFolderPath = "$($ConfigurationFolder)\$($data.RelativeFolderPath)"
        $webUrl = "$($PortalUrl)$($data.RelativeWebUrl)"
        ImportListDataWithNotification $webUrl $importedDataFolderPath
    }
}

# -----------------------------------------------
# Функция проверки состояния службы
# -----------------------------------------------
function CheckServiceRunning([string]$spServiceName, [string]$notRunSPServiceMessage)
{
    $spService = Get-WmiObject win32_service | Where-Object {$_.name -eq $spServiceName}
    $spServiceRunning = $spService.State -eq "Running"
    if (-not $spServiceRunning) {
		Start-Service $spServiceName
		Write-Host $spServiceName " service successfully started"
	}
}

#------------------------------------------------
# Проверка установленной версии SharePoint
#------------------------------------------------
function CheckSharePointSKU()
{
	$SharePointProducts = @{
		"88BED06D-8C6B-4E62-AB01-546D6005FE97" = "SharePoint Server 2010 Enterprise Trial";
		"D5595F62-449B-4061-B0B2-0CBAD410BB51" = "SharePoint Server 2010 Enterprise";
		"BC4C1C97-9013-4033-A0DD-9DC9E6D6C887" = "Search Server 2010 Trial";
		"08460AA2-A176-442C-BDCA-26928704D80B" = "Search Server 2010";
		"84902853-59F6-4B20-BC7C-DE4F419FEFAD" = "Project Server 2010 Trial";
		"ED21638F-97FF-4A65-AD9B-6889B93065E2" = "Project Server 2010";
		"1328E89E-7EC8-4F7E-809E-7E945796E511" = "Search Server Express 2010";
		"B2C0B444-3914-4ACB-A0B8-7CF50A8F7AA0" = "SharePoint Server 2010 Standard Trial";
		"3FDFBCC8-B3E4-4482-91FA-122C6432805C" = "SharePoint Server 2010 Standard";
		"926E4E17-087B-47D1-8BD7-91A394BC6196" = "Office Web Companions 2010";		
		"BEED1F75-C398-4447-AEF1-E66E1F0DF91E" = "SharePoint Foundation 2010";
		"B7D84C2B-0754-49E4-B7BE-7EE321DCE0A9" = "SharePoint Server 2013 Enterprise";
		"C5D855EE-F32B-4A1C-97A8-F0A28CE02F9C" = "SharePoint Server 2013";
		"9FF54EBC-8C12-47D7-854F-3865D4BE8118" = "SharePoint Foundation 2013"
		}
		
	$SharePointProductsRegistryPath2013 = "SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\15.0\WSS\InstalledProducts\"
	$register = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($SharePointProductsRegistryPath2013,$false)

	if ($register -eq $null)
	{
		$SharePointProductsRegistryPath2010 = "SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\WSS\InstalledProducts\"
		$register = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($SharePointProductsRegistryPath2010,$false)
	}
	
	$regKeys = @()
	foreach($value in $register.GetValueNames()) {
	  	$SKUId = [string]$register.GetValue($value);
		$regKeys += ,$SKUId
	}								 

	foreach($key in $SharePointProducts.Keys)
	{
		if($regKeys -contains $key) {
			return $SharePointProducts[$key]
		}
	}
	
	return $null
}

if($NonCheckRequirements -ne $True)
{
	CheckInstallRequirements $PortalUrl
}


# -----------------------------------------------
#  Старт
# -----------------------------------------------
Try
{
Start-SPAssignment

$installedVersion = CheckSharePointSKU

if ($installedVersion) {
	Write-Host $installedVersion -ForegroundColor: DarkYellow
}
else {
	throw "SharePoint2013 not found"
}

CheckServiceRunning -spServiceName "SPAdminV4" -notRunSPServiceMessage "Служба администратора Sharepoint (SPAdminV4) не запущена"
CheckServiceRunning -spServiceName "SPuserCodeV4" -notRunSPServiceMessage "Служба изолированного кода (SPuserCodeV4) не запущена"
CheckServiceRunning -spServiceName "SPTimerV4" -notRunSPServiceMessage "Служба таймера (SPTimerV4) не запущена"

# Читаем файл настройки
$ConfigurationXml = [xml](Get-Content "$ConfigurationFile" -Encoding: UTF8 -ErrorAction: Stop)
$ConfigurationXml.PreserveWhitespace = $false
$Configuration = $ConfigurationXml.Configuration

if($Configuration.SdcInstallator)
{
	. $("$execFolder\SdcUI.ps1")
}

$ConfigurationFolder = Split-Path $ConfigurationFile
Write-Host "Директория конфигурации: " $ConfigurationFolder -ForegroundColor: DarkYellow


# Параметры
if ($PortalUrl -eq $null) # адрес портала
{
    $portalUrlParam = GetParamValue -paramName: "PortalUrl"     
    if ($portalUrlParam -eq $null)
    {   
        throw "Не задан адрес портала"        
    } 
    else
    {
        $PortalUrl = $portalUrlParam
    }   
}    

Write-Host "Адрес портала:" $PortalUrl -ForegroundColor: Green

if($Configuration.Solutions)
{
    Write-Host 1.Решения
    AddAndInstallSolutions -Solutions: $Configuration.Solutions
    Write-Host
}

Start-Sleep -Seconds 10

if($Configuration.WebApplication)
{
    Write-Host 2.Веб приложение
    ActivateWebApplicationFeatures -Features: $Configuration.WebApplication.Features
    Write-Host
}

if($Configuration.SiteCollection)
{
    Write-Host 3.Семейство сайтов
	$SiteUrl = "/"
	if($Configuration.SiteCollection.SiteUrl)
	{
		$SiteUrl = $Configuration.SiteCollection.SiteUrl
	}
    ActivateSiteCollectionFeatures -Features: $Configuration.SiteCollection.Features -SiteUrl: "$PortalUrl/$SiteUrl"
    Write-Host
}


if($Configuration.Sites)
{
    Write-Host 4. Cайты
    Write-Host $Configuration.Sites.Site.ThemeSettings.Color
    # Создаем словарь [Тип сайта, {Наименование шаблона, Набор возможностей, Объединненные календари, Свойства для PropertyBag }] 
    $dictSiteTypeInfo = @{}
    if($Configuration.Types)
    {
        foreach ($type in $Configuration.Types.Type)
        {    
            $dictSiteTypeInfo.Add($type.Name, @{Template = $type.Template; Features = $type.Features.Feature; CalendarOverlays = $type.CalendarOverlays.CalendarOverlay; Properties = $type.Properties; ThemeSettings = $type.ThemeSettings} )
        }
    }

    # Конфигурируем сайты
    ConfigurationSites -BaseUrl: $PortalUrl -Sites: $Configuration.Sites 

    Write-Host
}


if($Configuration.ImportedData)
{
    Write-Host 5. Импортируемые данные
    ImportData -ImportedData: $Configuration.ImportedData
    Write-Host
}


if($Configuration.TopNavigationBar)
{
    Write-Host 6. Главное меню
	$webUrl = "/"
	
	if($Configuration.TopNavigationBar.WebUrl)
	{
		$webUrl = "$PortalUrl" + $Configuration.TopNavigationBar.WebUrl;
	}
	else
	{
		$webUrl = $PortalUrl;
	}
	
	$web = Get-SPWeb $webUrl;
	
	DeleteNavigationLinks $web
	$navigationXml = $Configuration.TopNavigationBar.OwnerDocument
	ImportNavigationMenu $web $navigationXml
	
    Write-Host
}

if ($Configuration.WebConfig)
{
	Write-Host 7. Веб-конфигурация	
	if ($Configuration.WebConfig.providers)
	{
		if ($Configuration.WebConfig.IISSiteName)
		{
			$iisSiteName = $Configuration.WebConfig.IISSiteName;
			foreach ($item in $Configuration.WebConfig.providers.add)
			{
				AddProvider $iisSiteName $item
			}
			Write-Host Данные добавленны
		}
		else
		{			
			Write-Host Имя сайта не указано
		}

	}	
}

Write-Host 8. Деактивация минимальной загрузки
DisableMinimalDownload -PortalUrl: $PortalUrl
Write-Host

Write-Host ОК!

Stop-SPAssignment -global
}
catch [Exception]
{
		Write-Host 'Возникло исключение: '$_.Exception.Message -ForegroundColor Red
		Write-Host $_.Exception.ToString() -ForegroundColor Red
		Throw
	
}
try{ Stop-Transcript }
catch{}