param([string]$sparkasse)

# $CommonLogFile = $PSScriptroot + "/Data/Profil-Common-$(Get-Date -Format yyyyMMdd-HHmmss).log"
# Start-Transcript -Path $CommonLogFile -Append
# try
# {
# just to be sure where we are - not really needed
Set-Location $PSScriptroot


$ErrorActionPreference = "SilentlyContinue" 
$global:ErrorActionPreference = "SilentlyContinue" 

# $ErrorActionPreference = "Stop"
# $global:ErrorActionPreference = "Stop"
# trap
# {
#     Write-Host "=== UNHANDLED EXCEPTION ===" -ForegroundColor Red
#     Write-Host "Message : $($_.Exception.Message)" -ForegroundColor Red
#     Write-Host "Type    : $($_.Exception.GetType().FullName)" -ForegroundColor Yellow
#     Write-Host "Position:" -ForegroundColor Yellow
#     Write-Host $_.InvocationInfo.PositionMessage
#     Write-Host "ScriptStackTrace:" -ForegroundColor Yellow
#     Write-Host $_.ScriptStackTrace
#     break   # hard stop
# }

# $ErrorActionPreference = "Continue"
# $ErrorActionPreference = "SilentlyContinue"

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'

. "$PSScriptroot/Process-ADObjects-Configuration.ps1"
# one may override configuration settings here - for local settings you should tag it with "SVN-IGNORE"
if (Test-Path -Path "$PSScriptroot/Process-ADObjects-Configuration-Local.ps1")
{
  . "$PSScriptroot/Process-ADObjects-Configuration-Local.ps1"
}


# --------------------------------------------------------------
# read additional sources  - better keep the sequence order !
# --------------------------------------------------------------
. $PSScriptroot/Process-ADObjects-Utility.ps1
. $PSScriptroot/Process-ADObjects-Base.ps1
. $PSScriptroot/Process-ADObjects-Analyze.ps1
. $PSScriptroot/Process-ADObjects-Work.ps1

$TimeStamp = getTimeStamp

$Institut = checkInput($sparkasse)
$InstituteRootPath = $Config.DataRootPath + $Institut + "/"
$InstituteRootPathIn = $InstituteRootPath + "In/"
$InstituteRootPathTmp = $InstituteRootPath + "Tmp/"
$InstituteRootPathLog = $InstituteRootPath + "Log/"
$InstituteRootPathOut = $InstituteRootPath + "Out/"
$LogFileName = $InstituteRootPathLog + [io.path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name) + "-" + $TimeStamp + ".log"
Remove-Item -Path $LogFileName -ErrorAction Ignore
$IsTestMode = checkTestMode
$InstitutsSourcePath = $PSScriptroot + "/Process-ADObjects-Work-" + $Institut + ".ps1"
$InstitutsSourcePathKURS = $PSScriptroot + "/Process-ADObjects-Work-" + $Institut + "-KURS.ps1"
$InstitutsSourcePathDAW = $PSScriptroot + "/Process-ADObjects-Work-" + $Institut + "-DAW.ps1"
if (checkInputSourceFiles)
{
  . $InstitutsSourcePath
  # source it only when needed - se below
  # . $InstitutsSourcePathKURS
  # . $InstitutsSourcePathDAW
}

$ADObjectsFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_ADObjects_*" + ".csv"
$ADObjectMembershipsFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_ADObjectMemberships_*" + ".csv"
# ------>>>    use '*' to get last entry by name as done before
# $ADApplicationsFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Anwendungen*" + ".csv"
# $ADDirectoriesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Verzeichnisse*" + ".csv"
# $SecuritySettingsInFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Sicherheitseinstellungen*" + ".csv"
# $KURSEmployeesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Mitarbeiter*" + ".csv"
# $KURSPositionsFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_P014_Stellen*" + ".csv"
# $ADFKRolesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_FKRollen*" + ".csv"
# $ADOERolesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_OERollen*" + ".csv"
# $ADRCRolesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_RCRollen*" + ".csv"
# $ADOtherRolesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_SonstigeRollen*" + ".csv"

$ADApplicationsFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Anwendungen" + ".csv"
$ADDirectoriesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Verzeichnisse" + ".csv"
$SecuritySettingsInFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Sicherheitseinstellungen" + ".csv"
$KURSEmployeesFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Mitarbeiter" + ".csv"
$KURSPositionsFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_Stellen" + ".csv"
$DAWProfileInFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_DAWRollenzuordnungen" + ".csv"
$KURSPositionfunctionsPositionsInFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_KURSStellenfunktionen-Stellen" + ".csv"
$KURSProfileEmployeeInFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_KURSProfile-Mitarbeiter" + ".csv"
$KURSProfileDAWRightsInFilePathRegExp = "$InstituteRootPathIn" + $Institut + "_KURSProfile-DAWBerechtigungen" + ".csv"

################ this is NEW input ##################################################################
$KURSProfileNumberMapping = "$InstituteRootPathIn" + $Institut + "_ProfilNummernMapping" + ".csv"
$KURSProfilePrefixes = "$InstituteRootPathIn" + $Institut + "_ProfilPrefixe" + ".csv"
################ this is NEW input ##################################################################

$ADObjectsFilePath = Get-ChildItem -Path $ADObjectsFilePathRegExp | Sort-Object Name | Select-Object -Last 1
$ADObjectMembershipsFilePath = Get-ChildItem -Path $ADObjectMembershipsFilePathRegExp | Sort-Object Name | Select-Object -Last 1

$ADApplicationsInFilePath = Get-ChildItem -Path $ADApplicationsFilePathRegExp | Sort-Object Name | Select-Object -Last 1
$ADDirectoriesInFilePath = Get-ChildItem -Path $ADDirectoriesFilePathRegExp | Sort-Object Name | Select-Object -Last 1
$KURSEmployeesInFilePath = Get-ChildItem -Path $KURSEmployeesFilePathRegExp | Sort-Object Name | Select-Object -Last 1
$SecuritySettingsInFilePath = Get-ChildItem -Path $SecuritySettingsInFilePathRegExp | Sort-Object Name | Select-Object -Last 1
$KURSPositionsInFilePath = Get-ChildItem -Path $KURSPositionsFilePathRegExp | Sort-Object Name | Select-Object -Last 1


# temporary !!! just to keep existing coding
$DirectoriesInFilePath = $ADDirectoriesInFilePath
$ApplicationsInFilePath = $ADApplicationsInFilePath
$MitarbeiterInFilePath = $KURSEmployeesInFilePath
$SecurityInFilePath = $SecuritySettingsInFilePath

$FI = $Config.FI
$SPK = $Config.SPK[$Institut]
$SPKR = $SPK.Region.Trim() 
$SPKNO = $SPK.No.Trim()
$SPKID = $SPKR + $SPKNO

# put RootDomainName-Setting into $SPK, so there`s no need to do erroneous calculations  
# $SPK.RootDomainName = $FI.RootDomainName + $SPK.Region

if (-not (checkInputDataFiles))
{
  outLog "error in checkInputDataFiles() - exiting ..."
  exit
}

$AppAccessTmpFilePath = "$InstituteRootPathTmp" + $Institut + "_AppAccess_" + $TimeStamp + ".csv"
$FilesystemAccessTmpFilePath = "$InstituteRootPathTmp" + $Institut + "_FilesystemAccess_" + $TimeStamp + ".csv"
$AppConfigurationTmpFilePath = "$InstituteRootPathTmp" + $Institut + "_AppConfiguration_" + $TimeStamp + ".csv"
$OrganisationTmpFilePath = "$InstituteRootPathTmp" + $Institut + "_Organisation_" + $TimeStamp + ".csv"
$SecurityTmpFilePath = "$InstituteRootPathTmp" + $Institut + "_Security_" + $TimeStamp + ".csv"
$RoleTmpFilePath = "$InstituteRootPathTmp" + $Institut + "_Role_" + $TimeStamp + ".csv"

$DAWGruppenverwaltungOutFilePath = "$InstituteRootPathOut" + $Institut + "_Gruppenverwaltung_" + $TimeStamp + ".csv"
$DAWGruppenverwaltungNeuOutFilePath = "$InstituteRootPathOut" + $Institut + "_Gruppenverwaltung_neu_" + $TimeStamp + ".csv"
$KURSIstProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-Profile_" + $TimeStamp + ".csv"
$KURSIstProfileBerechtigungenOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-ProfileBerechtigungen_" + $TimeStamp + ".csv"
$KURSIstStellenBerechtigungenOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-StellenBerechtigungen_" + $TimeStamp + ".csv"
$KURSIstStellenProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-StellenProfile_" + $TimeStamp + ".csv"

$KURSIstOEsBerechtigungenOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-OEsBerechtigungen_" + $TimeStamp + ".csv"
$KURSIstOEsProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-OEsProfile_" + $TimeStamp + ".csv"
$KURSIstMitarbeiterProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_Ist-MitarbeiterProfile_" + $TimeStamp + ".csv"

$KURSSollStellenfunktionenOutFilePath = "$InstituteRootPathOut" + $Institut + "_Soll-Stellenfunktionen_" + $TimeStamp + ".csv"

$KURSSollProfileBerechtigungenOutFilePath = "$InstituteRootPathOut" + $Institut + "_Soll-ProfileBerechtigungen_" + $TimeStamp + ".csv"
$KURSSollStellenfunktionenBerechtigungenOutFilePath = "$InstituteRootPathOut" + $Institut + "_Soll-StellenfunktionenBerechtigungen_" + $TimeStamp + ".csv"
$KURSSollStellenfunktionenProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_Soll-StellenfunktionenProfile_" + $TimeStamp + ".csv"

# we need #DAWGruppenAnlegenOutFilePathRegExp to be able to separate the two phases "ProcessDAW" and "WriteKURS" by retrieving the last writte outfile
$DAWGruppenAnlegenOutFilePathBody = "$InstituteRootPathOut" + $Institut + "_GruppenAnlegen_"
$DAWGruppenAnlegenOutFilePathRegExp = $DAWGruppenAnlegenOutFilePathBody + "*.csv"
$DAWGruppenAnlegenOutFilePath = $DAWGruppenAnlegenOutFilePathBody + $TimeStamp + ".csv"
# we need #KURSSollProfileOutFilePathRegExp to be able to separate the two phases "ProcessDAW" and "WriteKURS" by retrieving the last writte outfile
$KURSSollProfileOutFilePathBody = "$InstituteRootPathOut" + $Institut + "_Soll-Profile_"
$KURSSollProfileOutFilePathRegExp = $KURSSollProfileOutFilePathBody + "*.csv"
$KURSSollProfileOutFilePath = $KURSSollProfileOutFilePathBody + $TimeStamp + ".csv"

$DAWStellenfunktionenProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_DAWStellenfunktionen-Profile_" + $TimeStamp + ".csv"
$DAWStellenProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_DAWStellen-Profile_" + $TimeStamp + ".csv"
$DAWMitarbeiterProfileOutFilePath = "$InstituteRootPathOut" + $Institut + "_DAWMitarbeiter-Profile_" + $TimeStamp + ".csv"

$ADObjects = $null
$ADObjectMemberships = $null
$ADObjectsAppAccess = @()
$ADObjectsFilesystemAccess = @()
$ADObjectsAppConfiguration = @()
$ADObjectsOrganisation = @()
$ADObjectsSecurity = @()
$ADObjectsRole = @()

$ADApplications = Get-Content -Path $ADApplicationsInFilePath | ConvertFrom-Csv -Delimiter ";" 
$ADDirectories = Get-Content -Path $ADDirectoriesInFilePath | ConvertFrom-Csv -Delimiter ";" 
$Employees = Get-Content -Path $KURSEmployeesInFilePath | ConvertFrom-Csv -Delimiter ";" 
$SecuritySettings = Get-Content -Path $SecuritySettingsInFilePath | ConvertFrom-Csv -Delimiter ";" 
$KURSPositionEmployees = Get-Content -Path $KURSPositionsInFilePath | ConvertFrom-Csv -Delimiter ";" 

if ($Config.Verbose)
{
  # Write-host  ($PSVersionTable | Format-Table -Force | Out-String)
  # Write-host $PSScriptroot 
  outLog ($PSVersionTable | Format-Table -Force | Out-String)
  outLog $PSScriptroot 
  Get-Variable | Out-String
}

$startTime = Get-Date
outLog "started:  ========================================================== " $startTime.ToString("yyyy.MM.dd-HH:mm:ss.mmm")

# $ADObjects = Import-Csv -Path $ADObjectsFilePath -Delimiter ";"
# ToDo: "GDT-Smartcard"-Filter is not necessarily ok her - it`s done 
$ADObjects = Import-Csv -Path $ADObjectsFilePath -Delimiter ";" #| Where-Object { -not ($_.ObjectName.StartsWith($Institut + "GDT-Smartcard")) }
$ADObjectMemberships = Import-Csv -Path $ADObjectMembershipsFilePath -Delimiter ";"
$ADObjectMembershipsIndexed = newObjectMembershipsIndex $ADObjectMemberships

if ($Config.Analyze)
{
  analyzeDirectoryPaths
}

$importingTime = Get-Date
# Write-Host "finished: importing at" $importingTime.ToString("yyyy.MM.dd-HH:mm:ss.mmm")", used" ($importingTime - $startTime) 
outLog "finished: importing at " $importingTime.ToString("yyyy.MM.dd-HH:mm:ss.mmm") ", used " ($importingTime - $startTime) 

"Name;Path;ShortCut;Description" | Out-File "$AppAccessTmpFilePath" -Encoding "utf8NoBom" 
"Name;Path;ShortCut;Description" | Out-File "$FilesystemAccessTmpFilePath" -Encoding "utf8NoBom" 
"Name;Path;ShortCut;Description" | Out-File "$AppConfigurationTmpFilePath" -Encoding "utf8NoBom" 
"Name;Path;ShortCut;Description" | Out-File "$OrganisationTmpFilePath" -Encoding "utf8NoBom" 
"Name;Path;ShortCut;Description" | Out-File "$SecurityTmpFilePath" -Encoding "utf8NoBom" 
"Name;Path;ShortCut;Description" | Out-File "$RoleTmpFilePath" -Encoding "utf8NoBom" 


$preparingTime = Get-Date
$ADObjectsOrganisation += prepareADObjectsByType $FI.TypeTagOrganisation
$ADObjectsAppAccess += prepareADObjectsByType $FI.TypeTagAppAccess
$ADObjectsFilesystemAccess += prepareADObjectsByType $FI.TypeTagFilesystemAccess
$ADObjectsAppConfiguration += prepareADObjectsByType $FI.TypeTagAppConfiguration
$ADObjectsSecurity += prepareADObjectsByType $FI.TypeTagSecurity
$ADObjectsRole += prepareADObjectsByType $FI.TypeTagRole

$preparingTime = Get-Date
# Write-Host "finished: preparing at " $preparingTime.ToString("yyyy.MM.dd-HH:mm:ss.mmm")", used" ($preparingTime - $importingTime) 
outLog "finished: preparing at " $preparingTime.ToString("yyyy.MM.dd-HH:mm:ss.mmm") ", used " ($preparingTime - $importingTime) 
outlog "found " $ADObjectsOrganisation.Count " entries of type " $FI.TypeTagOrganisation
outlog "found " $ADObjectsAppAccess.Count " entries of type " $FI.TypeTagAppAccess
outlog "found " $ADObjectsFilesystemAccess.Count " entries of type " $FI.TypeTagFilesystemAccess
outlog "found " $ADObjectsAppConfiguration.Count " entries of type " $FI.TypeTagAppConfiguration
outlog "found " $ADObjectsSecurity.Count " entries of type " $FI.TypeTagSecurity
outlog "found " $ADObjectsRole.Count " entries of type " $FI.TypeTagRole

$processingTime = Get-Date

# --------------------------------------------------------------
# Generierte 'OU' Dateien abarbeiten um die Generierung der neuen Gruppen anzustossen
# --------------------------------------------------------------

if ($Config.ProcessDAW)
{
  $ProcessDAWStartTime = Get-Date
  WriteHeaders
  try
  {
    ProcessADObjects $ADObjectsOrganisation $FI.TypeTagOrganisation
    ProcessADObjects $ADObjectsAppAccess $FI.TypeTagAppAccess
    ProcessADObjects $ADObjectsFileSystemAccess $FI.TypeTagFileSystemAccess
    ProcessADObjects $ADObjectsSecurity $FI.TypeTagSecurity
    ProcessADObjects $ADObjectsAppConfiguration $FI.TypeTagAppConfiguration
    ProcessADObjects $ADObjectsRole $FI.TypeTagRole
  }
  catch 
  {
    writeExceptionInfo $_ -Rethrow
  }
  $ProcessDAWEndTime = Get-Date
}
else
{
  outLog "ProcessDAW is disabled in configuration !!!"
}


# --------------------------------------------------------------
# Write KURS-Ladetabellen für IST und SOLL
# --------------------------------------------------------------
if ($Config.WriteKURS)
{
  $startTimeWriteKURS = Get-Date
  . $InstitutsSourcePathKURS
  WriteKURS
  $endTimeWriteKURS = Get-Date
  outLog "finished: processing WriteKURS at " $endTimeWriteKURS.ToString("HH:mm:ss.mmm")", used " ($endTimeWriteKURS - $startTimeWriteKURS)
}
else
{
  outLog "WriteKURS is disabled in configuration !!!"
}

if ($Config.TransferDAW)
{
  $startTimeTransferDAW = Get-Date
  . $InstitutsSourcePathDAW
  TransferDAW
  $endTimeTransferDAW = Get-Date
  outLog "finished: processing TransferDAW at " $endTimeTransferDAW.ToString("HH:mm:ss.mmm")", used " ($endTimeTransferDAW - $startTimeTransferDAW)
}
else
{
  outLog "TransferDAW is disabled in configuration !!!"
}

if ($Config.PostProcess)
{
  $startTimePostProcess = Get-Date
  postProcess
  $endTimePostProcess = Get-Date
  outLog "finished: processing PostProcess at " $endTimePostProcess.ToString("HH:mm:ss.mmm")", used " ($endTimePostProcess - $startTimePostProcess)
}
else
{
  outLog "PostProcess is disabled in configuration !!!"
}


$endTime = Get-Date
outLog "finished: processing at " $endTime.ToString("HH:mm:ss.mmm")", used " ($endTime - $processingTime) 
outLog "finished: ========================================================== " $endTime.ToString("yyyy.MM.dd-HH:mm:ss.mmm") 
outLog "used:     "($endTime - $startTime)

# }
# finally
# {
#     Stop-Transcript
# }

