[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$egurkhaPath=(Get-Item Env:EGURKHA_INSTALL_DIR).value.ToString()
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$egEncryPath=$scriptPath+"\EGFileEncryption.psm1"
$egDatnKy=$scriptPath+"\GetDatnKeyFiles.psm1"
Import-Module $egEncryPath,$egDatnKy

$testargs=$args
$userName=$testargs[0]
$Password=Eg-O365Dcr -EncStr $testargs[1]
$Proxycrds=$testargs[2]
$pxycrds=$Proxycrds.split("#")
$proxyUsr=$pxycrds[0]
$proxyPass=Eg-O365Dcr -EncStr $pxycrds[1]
$rName=$testargs[3]
$AuditMailbxs=$testargs[4]

$azureVal=Eg-GetAzureEnv -UserName $userName
$azureEnvArr=$azureVal.Split(',')
if($proxyUsr.toString().toLower().Trim() -eq 'none') { $proxyUsr=$proxyUsr.toString().toLower().Trim() }
if($proxyPass.toString().toLower().Trim() -eq 'none') { $proxyPass=$proxyPass.toString().toLower().Trim() }

$RprtNameAndmTime=$rName.split("#")
$reportingname=$RprtNameAndmTime[0]
$mTime=$RprtNameAndmTime[1]

#----------------------------------
$domainSpecific=$false
if($reportingname -match '_exd'){
    $domainSpecific=$true
    $alldomainnames=@()
    $dhash=Eg-O635Domains -username $userName -password $Password -rptNam $reportingname -proxyserverip 'none' -proxyUsr $proxyUsr -proxyPass $proxyPass
    $reportingname=$dhash['SupersetName']
    foreach($h in $dhash.Keys){
        if($h -ne 'SupersetName'){
            $alldomainnames+=$h
        }
    }
    $ds_ADOwn_Key='';$ds_ADOwn_fpth='';$ds_ADOwn_nam='';
    $ds_ADNown_Key='';$ds_ADNown_fpth='';$ds_ADNown_nam='';
    $ds_ADDlp_Key='';$ds_ADDlp_fpth='';$ds_ADDlp_nam='';
}
$rptPath='EXO/'+$reportingname
$chkwritPath=$egurkhaPath+'/agent/'+$rptPath
if($domainSpecific){ 
    $isWrite=Check-WriteFile -rptPath $chkwritPath -srchWrd 'EXOAuditLog' -mTimInMin $mTime
}

$isProceed=$false
if($isWrite){
    $isProceed=$true
}elseif($domainSpecific -eq $false){
    $isProceed=$true
}else{
    $isProceed=$false
}
#-----------------------------------------------------

if($isProceed){
    $ManualThrottle=0
    [double]$ActiveThrottle=.25
    $ResetSeconds=870
    $WriteLog=$true
    $LogFile = $egurkhaPath+'/agent/EXO/'+$reportingname+"\audits.log"
    $LogFile1 = $egurkhaPath+'/agent/EXO/'+$reportingname+"\audits1.log"
    $isFrstTimLog=$true

    # Writes output to a log file with a time date stamp
    Function Write-Log {
	    Param ([string]$string)
	    [string]$date = Get-Date -Format G
        if ($WriteLog) {
           ( "[" + $date + "] - [" + $reportingname+"] mTime -  " + $mTime + " - " + $string ) | Out-File -FilePath $LogFile -Append 
        } 
        if($isFrstTimLog){     
            if ($WriteLog -eq $true){ #if flag is true 
                if ([System.IO.File]::Exists($LogFile) -and (Get-Item $LogFile).length -gt 2mb) {  #if the size of file is greater than 1MB 
                    if([System.IO.File]::Exists($LogFile1)){  #if logfile1 already exists, delete logfile1 
                        Remove-Item $LogFile1 
                    } 
                    Rename-Item $LogFile $LogFile1 
                }
            }
            $isFrstTimLog=$false
        }
    }

    Function Start-SleepWithProgress {
	    Param([int]$sleeptime)
	    For ($i=0;$i -le $sleeptime;$i++){
		    $timeleft = ($sleeptime - $i);
		    Write-Progress -Activity "Sleeping" -CurrentOperation "$Timeleft More Seconds" -PercentComplete (($i/$sleeptime)*100);
		    start-sleep 1
	    }
	    Write-Progress -Completed -Activity "Sleeping"
    }

    Function New-CleanO365Session {
        $Credential = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $Password -asplaintext -force)
        $i = 0
	    while (($Credential -eq $Null) -and ($i -lt 5)){
		    $script:Credential = Get-Credential -Message "Please provide your Exchange Online Credentials"
		    $i++
	    }
	    if ($Credential -eq $null){
		    Write-log "[Error] - Failed to get credentials"
		    Write-Error -Message "Failed to get credentials" -ErrorAction Stop
	    }
	    Write-Log "Removing all PS Sessions"
	    Get-PSSession | Remove-PSSession -Confirm:$false
	    [System.GC]::Collect()
	    Write-Log ("Sleeping 15 seconds for Session Tear Down")
	    Start-SleepWithProgress -SleepTime 15
	    $Error.Clear()
	
	    # Create the session
	    Write-Log "Creating new PS Session"
	    $sessionOption = New-PSSessionOption -SkipRevocationCheck
	    if($proxyUsr -ne 'none' -and $proxyPass -ne 'none'){
	        $proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $proxyUsr, $(convertto-securestring $proxyPass -asplaintext -force)
	        $sessionOption = New-PSSessionOption -SkipRevocationCheck -ProxyAccessType WinHttpConfig -ProxyAuthentication basic -ProxyCredential $proxyCred
	    }
	    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $azureEnvArr[1] -Credential $Credential -Authentication Basic -AllowRedirection -SessionOption $sessionOption -WarningAction SilentlyContinue
		
	    # Check for an error while creating the session
	    if ($Error.Count -gt 0){
		    Write-Log "[ERROR] - Error while setting up session"
		    Write-log $Error
		    $ErrorCount++
		    if ($ErrorCount -gt 3){
			    $deleky=0
			    Write-log "[ERROR] - Failed to setup session after multiple tries"
			    Write-log "[ERROR] - Aborting Script"
			    exit		
		    }
		    Write-Log "Sleeping 60s so that issue can potentially be resolved"
		    Start-SleepWithProgress -sleeptime 60
		    New-CleanO365Session
	    }
	    else{
		    $ErrorCount = 0
	    }
	
	    # Import the PS session
	    $null = Import-PSSession $session -AllowClobber -WarningAction SilentlyContinue -DisableNameChecking
	
	    # Set the Start time for the current session
	    Set-Variable -Scope script -Name SessionStartTime -Value (Get-Date)
    }

    Function Test-O365Session {
	    $ObjectTime = Get-Date
	    $SessionInfo = $null
	    $SessionInfo = Get-PSSession
	    if ($SessionInfo -eq $null) { 
		    Write-Log "[ERROR] - No Session Found"
		    Write-log "Recreating Session"
		    New-CleanO365Session
	    }	
	    elseif ($SessionInfo.State -ne "Opened"){
		    Write-Log "[ERROR] - Session not in Open State"
		    Write-log ($SessionInfo | fl | Out-String )
		    Write-log "Recreating Session"
		    New-CleanO365Session
	    }
	    elseif (($ObjectTime - $SessionStartTime).totalseconds -gt $ResetSeconds){
		    Write-Log ("Session Has been active for greater than " + $ResetSeconds + " seconds" )
		    Write-Log "Rebuilding Connection"
		    [int]$DelayinSeconds = ((($ResetSeconds * $ActiveThrottle) / 2) - 15)
		    if ($DelayinSeconds -gt 0){
			    Write-Log ("Sleeping " + $DelayinSeconds + " addtional seconds to allow throttle recovery")
			    Start-SleepWithProgress -SleepTime $DelayinSeconds
		    }
		    else {
			    Write-Log ("Active Delay calculated to be " + ($DelayinSeconds + 15) + " seconds no addtional delay needed")
		    }
		    New-CleanO365Session
	    }
	    else{
	    }
	    if ($ManualThrottle -gt 0){
		    Write-log ("Sleeping " + $ManualThrottle + " milliseconds")
		    Start-Sleep -Milliseconds $ManualThrottle
	    }
    }

    Function Get-EstimatedTimeToCompletion {
	    param([int]$ProcessedCount)
	    $ProcessedCount++
	    if (($ProcessedCount % 100) -eq 0){
		    $CurrentDate = Get-Date
		    $AveragePerObject = (((($CurrentDate) - $ScriptStartTime).totalseconds) / $ProcessedCount)
		    Write-Log ("[STATS] - Total Number of Objects:     " + $ObjectCount)
		    Write-Log ("[STATS] - Number of Objects processed: " + $ProcessedCount)
		    Write-Log ("[STATS] - Average seconds per object:  " + $AveragePerObject)
		    Write-Log ("[STATS] - Estimated completion time:   " + $CurrentDate.addseconds((($ObjectCount - $ProcessedCount) * $AveragePerObject)))
	    }
	    return $ProcessedCount
    }


    $rptPath='EXO/'+$reportingname
    $MyDir=$egurkhaPath+'/agent/EXO/'+$reportingname
    if(!(Test-Path -Path $MyDir )){
        New-Item -ItemType directory -Path $MyDir
    }
    $isErrorOccur= $false

    $endDat = Get-Date
    $startDateDlp = Get-Date -Hour 00 -Minute 00 -Second 00
    $startDateDlp=$startDateDlp.AddMinutes(-1440)
    $startDat=$endDat.AddMinutes(-$mTime)

    Set-StrictMode -Version 2
    $ErrorCount = 0
    New-CleanO365Session
    $ScriptStartTime = Get-Date
    
    try{
        Test-O365Session
        $Error.Clear()
        $ownerActvts = Eg-WriteFile -ComntRptPath $rptPath -FileName "owneractvts" -keyFileName "kowneractvts" -EgPath $egurkhaPath
        Try{
            try{
                if($AuditMailbxs.Contains(',')){
                    $AuditMailbxs=$AuditMailbxs.Split(',')
                }
            }
            catch{
                $AuditMailbxs=" "
                write-Log "error occured while spliting the Mailbox Owners ID"
            }
            foreach( $Mailbx in  $AuditMailbxs){
                Search-MailboxAuditLog -Identity $Mailbx -StartDate $startDat -EndDate $endDat  -LogonTypes Owner -ShowDetails -ResultSize 1000 | 
                                        select Operation, LastAccessed, OperationResult, LogonType, ExternalAccess, DestFolderId, 
                                                DestFolderPathName, FolderId, FolderPathName, ClientInfoString, ClientIPAddress, 
                                                ClientMachineName, ClientProcessName, ClientVersion, InternalLogonType, 
                                                MailboxOwnerUPN, DestMailboxOwnerUPN, CrossMailboxOperation, LogonUserDisplayName, 
                                                SourceItems, SourceFolders, SourceItemIdsList, SourceItemSubjectsList, SourceItemAttachmentsList, 
                                                SourceItemFolderPathNamesList, SourceFolderPathNamesList, ItemSubject, ItemAttachments, 
                                                DirtyProperties, OriginatingServer, MailboxGuid, MailboxResolvedOwnerName, IsValid, ObjectState | export-csv $ownerActvts[1] -Append
            }

        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running MailboxAuditLog : "+$ErrorMessage)
            $isErrorOccur=$true
        }
        try{
            if($isErrorOccur -eq $true -and (Get-Item $ownerActvts[1]).length -le 2kb){
                write-Log ("Deleting File ErrorMessage while running MailboxAuditLog : "+$Error) 
                Remove-Item $ownerActvts[1]
                $isErrorOccur=$false
            }else{
                $ds_ADOwn_Key=$ownerActvts[0];$ds_ADOwn_fpth=$ownerActvts[1];$ds_ADOwn_nam=$ownerActvts[2];
                $null=Protect-File  $ownerActvts[1] -Algorithm AES -KeyAsPlainText $ownerActvts[0] -RemoveSource
            }
        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("Error while changeing ownerActvts csv to dat : "+$ErrorMessage)
            write-Log "not given mailbox ids.So no dat file is created"        
        }

        Test-O365Session
        $Error.Clear()
        try{
            $nonOwnerActvts = Eg-WriteFile -ComntRptPath $rptPath -FileName "nonowneractvts" -keyFileName "knonowneractvts" -EgPath $egurkhaPath
            Search-UnifiedAuditLog -StartDate $startDat -EndDate $endDat -ResultSize 1000| 
                            select AuditData,RecordType | 
                            Where-Object {$_.RecordType -like 'Exchange*' -and $_.RecordType -ne 'ExchangeAdmin'} | export-csv $nonOwnerActvts[1]
        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running  non Owner Actvts : "+$ErrorMessage)   
            $isErrorOccur=$true
        } 
        if($isErrorOccur -eq $true -and (Get-Item $nonOwnerActvts[1]).length -le 2kb){
            write-Log ("Deleting File ErrorMessage while running  non Owner Actvts(UnifiedAuditLog) : "+$Error)  
            Remove-Item $nonOwnerActvts[1]
            $isErrorOccur=$false
        }else{
            $ds_ADNown_Key=$nonOwnerActvts[0];$ds_ADNown_fpth=$nonOwnerActvts[1];$ds_ADNown_nam=$nonOwnerActvts[2];
            $null=Protect-File  $nonOwnerActvts[1] -Algorithm AES -KeyAsPlainText $nonOwnerActvts[0] -RemoveSource
        }

        Test-O365Session
        $Error.Clear()
        try{
            $DLPDetails = Eg-WriteFile -ComntRptPath $rptPath -FileName "dlpdetails" -keyFileName "kdlpdetails" -EgPath $egurkhaPath
            Search-UnifiedAuditLog  -StartDate $startDateDlp -EndDate $endDat  -RecordType ComplianceDLPExchange  | select AuditData,CreationDate | export-csv $DLPDetails[1]
        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running  Dlp Details : "+$ErrorMessage)   
            $isErrorOccur=$true
        } 
        if($isErrorOccur -eq $true -and (Get-Item $DLPDetails[1]).length -le 2kb){
            write-Log ("Deleting File ErrorMessage while running  Dlp Details : "+$Error)  
            Remove-Item $DLPDetails[1]
            $isErrorOccur=$false
        }else{
            $ds_ADDlp_Key=$DLPDetails[0];$ds_ADDlp_fpth=$DLPDetails[1];$ds_ADDlp_nam=$DLPDetails[2];
            $null=Protect-File  $DLPDetails[1] -Algorithm AES -KeyAsPlainText $DLPDetails[0] -RemoveSource
        }
    } 
    catch {
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        Write-Log "ErrorMessage : " + $ErrorMessage   
        Write-Log "FailedItem : " + $FailedItem
    }
    Write-Log "Script Complete Destroying PS Sessions"
    Get-PSSession | Remove-PSSession -Confirm:$false
}

if($domainSpecific){
    #------------- 1.For Domain Specific - owneractvts ----------------------
    if($ds_ADOwn_fpth -ne ''){
        $adownFilePth=$ds_ADOwn_fpth -replace (".csv",".dat")   
        if((Get-Item -Path $adownFilePth).Length -gt 2KB){
            $null=Unprotect-File $adownFilePth -Algorithm AES -KeyAsPlainText $ds_ADOwn_Key
            $oacts= import-csv $ds_ADOwn_fpth
            $oactnam=$ds_ADOwn_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$oactnam
                foreach($tmpRes in $oacts){
                    if($tmpRes.MailboxOwnerUPN -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$oactnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_ADOwn_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_ADOwn_Key -RemoveSource
                }
            }
        }
    }

    #------------- 2.For Domain Specific - nonowneractvts ----------------------
    if($ds_ADNown_fpth -ne ''){
        $adNownFilePth=$ds_ADNown_fpth -replace (".csv",".dat")   
        if((Get-Item -Path $adNownFilePth).Length -gt 2KB){
            $null=Unprotect-File $adNownFilePth -Algorithm AES -KeyAsPlainText $ds_ADNown_Key
            $nonoacts= import-csv $ds_ADNown_fpth
            $nonactnam=$ds_ADNown_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$nonactnam
                foreach($tmpRes in $nonoacts){
                    $actData=$tmpRes.AuditData |ConvertFrom-Json
                    if($actData.UserId -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$nonactnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_ADNown_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_ADNown_Key -RemoveSource
                }
            }
        }
    }

    #------------- 3.For Domain Specific - dlpdetails ----------------------
    if($ds_ADDlp_fpth -ne ''){
        $addlpFilePth=$ds_ADDlp_fpth -replace (".csv",".dat")   
        if((Get-Item -Path $addlpFilePth).Length -gt 2KB){
            $null=Unprotect-File $addlpFilePth -Algorithm AES -KeyAsPlainText $ds_ADDlp_Key
            $dlpDts= import-csv $ds_ADDlp_fpth
            $dtsnam=$ds_ADDlp_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$dtsnam
                foreach($tmpRes in $dlpDts){
                    $actData=$tmpRes.AuditData |ConvertFrom-Json
                    if($actData.UserId -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$dtsnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_ADDlp_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_ADDlp_Key -RemoveSource
                }
            }
        }
    }
}

$csvDir=$egurkhaPath+'/agent/EXO/'+$reportingname+'/'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'owneractvts'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'dlpdetails'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'nonowneractvts'