Set-Variable -Name 'scriptPath' -Value (Split-Path -parent $MyInvocation.MyCommand.Definition) -Scope Script -Force

Function Eg-InvokeGraphUrl(){
	[CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$Url,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$filePath,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$appId,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$appSecret,
        [Parameter(Mandatory=$true, Position=5)]
        [String]$authString,
        [Parameter(Mandatory=$true, Position=6)]
        [String]$resource
    )

    Process
    {
        $egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
		$langPath=$egurkhaPath+'\agent\config\O365_lang.ini'
		$encTyp=Eg-GetINIContent -Path $langPath -Subject 'File_Type' -Key 'encoding'
        $creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential" -ArgumentList $appId, $appSecret
        $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext"-ArgumentList $authString
        $context = $authContext.AcquireTokenAsync($resource, $creds).Result
        $authCode=$context.CreateAuthorizationHeader()

        $header = @{
            'Authorization'=$authCode
        }
		$queryRes = [System.Text.Encoding]::$encTyp.GetString((Invoke-WebRequest -Method Get -Headers $header -Uri $Url -UseBasicParsing).RawContentStream.ToArray())
        #$queryRes = Invoke-RestMethod -Method 'Get' -Headers $header -Uri $Url 
        $queryRes=$queryRes.Replace('ï»¿','')
        $queryRes=$queryRes.Replace('(Byte)','')
        $queryRes=$queryRes.Replace(' ','')
        $resultarray = ConvertFrom-Csv -InputObject $queryRes
        $reprts=$resultarray | ConvertTo-Json 
        $jsonreprt=@()
        $jsonreprt='{ "Usage" :['+$reprts+']}'
        $reports=$jsonreprt | ConvertFrom-Json
        for($i=0;$i -lt $reports.Usage.Length ;$i++ ){  
            $reports.Usage[$i] |Export-Csv $filePath -Encoding $encTyp -Append -NoTypeInformation -Force
        }
    }
}

Function Eg-WriteLog{
	Param (
    [String]$writString,
    [String]$LogPath,
    [String]$ReportingName,
    [String]$TestFreq,
    [boolean]$isWriteLog
    )
    $LogPath1=$LogPath.Replace(".log","1.log")
	[string]$date = Get-Date -Format G
    if ($isWriteLog -eq $true){
        ( "[" + $date + "] - [" + $ReportingName+"] mTime -  " + $TestFreq + " - " + $writString ) | Out-File -FilePath $LogPath -Append
        if ([System.IO.File]::Exists($LogPath) -and (Get-Item $LogPath).length -gt 2mb) {  #if the size of file is greater than 1MB 
            if([System.IO.File]::Exists($LogPath1)){  #if logfile1 already exists, delete logfile1 
                Remove-Item $LogPath1 
            } 
            Rename-Item $LogPath $LogPath1 
        }
    }
}

Function Eg-WriteFile(){
	[CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$ComntRptPath, 
        [Parameter(Mandatory=$true, Position=2)]
        [String]$FileName,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$keyFileName,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$EgPath
    )

    Process
    {
        $dir=$EgPath+'/agent/'+$ComntRptPath
        if(!(Test-Path -Path $dir )){
            $null=New-Item -ItemType directory -Path $dir
        }

        #clear dat and key files - start
        $clrPath=$dir+'/'
        $q=0;$tmpVal1='';$tmpVal2='';$tmpVal3='';$r=0;$tmpcsv1='';$tmpcsv2='';$tmpcsv3='';
        Get-ChildItem -Path $clrPath |Where-Object {$_.Name -like $FileName+'*'}| Sort-Object LastWriteTime -Descending |Select Name |ForEach-Object{
            if($_.Name -like $FileName+'*.dat' -and $q -lt 3){
                if($q -eq 0){$tmpVal1=$_.Name;}
                if($q -eq 1){$tmpVal2=$_.Name;}
                if($q -eq 2){$tmpVal3=$_.Name;}
                $q++
            }
            if($_.Name -like $FileName+'*.csv' -and $r -lt 3){
                if($r -eq 0){$tmpcsv1=$_.Name;}
                if($r -eq 1){$tmpcsv2=$_.Name;}
                if($r -eq 2){$tmpcsv3=$_.Name;}
                $r++
            }
            if($q -gt 3 -and $r -gt 3){
                break;
            }
        }
        Get-ChildItem -Path $clrPath |Where-Object {$_.Name -like $keyFileName+'*.dat' -or $_.Name -like $FileName+'*.dat' -or $_.Name -like $FileName+'*.csv'}| Sort-Object LastWriteTime -Descending |Select Name |ForEach-Object{
            if(!($tmpVal1 -eq $_.Name -or 'k'+$tmpVal1 -eq $_.Name -or $tmpVal2 -eq $_.Name -or 'k'+$tmpVal2 -eq $_.Name -or $tmpVal3 -eq $_.Name -or 'k'+$tmpVal3 -eq $_.Name -or $tmpcsv1 -eq $_.Name -or $tmpcsv2 -eq $_.Name -or $tmpcsv3 -eq $_.Name)){
                $rmvPath=$clrPath+$_.Name
                if([System.IO.File]::Exists($rmvPath)){
                    Remove-Item -Path $rmvPath
                }
            }
        }
        #clear dat and key files - end

        $timenow = [int][double]::Parse((Get-Date -UFormat %s))
        $writFilePath = $dir + "\"+$FileName+ $timenow +".csv"
        $keyName="\"+$keyFileName + $timenow + ".dat"
        $key=Get-CryptoKey -FileDir $dir -FileName $keyName
        $writeArr=@{}
        $writeArr[0]=$key  #key
        $writeArr[1]=$writFilePath #full path 
	    $writeArr[2]=$FileName+ $timenow +".csv" # file name 
        return $writeArr
    }
}

Function Eg-ReadFile(){
	[CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$ComntRptPath, 
        [Parameter(Mandatory=$true, Position=2)]
        [String]$FileName,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$keyFileName,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$EgPath
    )

    Process
    {
        $readFilePath=$EgPath+'/agent/'+$ComntRptPath+'/'
	    if ( Test-Path $readFilePath -PathType Container ) {
            $fileRead=Get-ChildItem -Path $readFilePath |Where-Object {$_.Name -like $FileName+'*.dat'}| Sort-Object LastWriteTime -Descending | Select-Object -first 1|Select Name
            if($fileRead -ne $null -and $fileRead -ne ''){
                $removFNam=$fileRead.name.toString().Replace($FileName,"")
                $tmpvalue=$removFNam.substring(0,$removFNam.length-4)
	            $kfileval = $keyFileName+$tmpvalue+".dat" 
                $currDat = [int][double]::Parse((Get-Date -UFormat %s))           
                $diffTicks=$currDat-[int]$tmpvalue
                if($diffTicks -gt 259200){
                    $logfilePath=$readFilePath+'egReadfile.log'
                    Eg-WriteLog -writString 'Latest dat files not found' -LogPath $logfilePath -ReportingName $ComntRptPath -isWriteLog $true
                    return $null
                }
            }else{
                return $null
            }
	        $kfile=Get-ChildItem -Path $readFilePath |Where-Object {$_.Name -eq $kfileval}| Sort-Object LastWriteTime -Descending | Select-Object -first 1|Select Name
	        $kfilename=([String]$kfile.Name).Trim()
        
	        $kvalue=Get-Content -Path $readFilePath$kfilename

	        $filePath=$readFilePath+$fileRead.Name
	        $unProtctPath=$filePath -replace (".csv",".dat")
            $readArr=@{}
            $readArr[0]=$kvalue  #Key
            $readArr[1]=$unProtctPath #Full Path
            $readArr[2]=$readFilePath # relative path
            $readArr[3]=$fileRead.name.toString() # file name 
            $readArr[4]=$kfileval #key file name
	    }
	    else{
		    New-Item -ItemType directory -Path $readFilePath
		    $readArr=@{}
	    }
        return $readArr
    }
}

Function Eg-DeleteFiles(){
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$FilePath, 
        [Parameter(Mandatory=$true, Position=2)]
        [String]$Pattern,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$InputFile  
    )
    Process
    {
        $indx=1
          $fileRead=Get-ChildItem -Path $FilePath |Where-Object {$_.Name -like $Pattern+'*.dat' -and $_.Name  -lt $InputFile }| Sort-Object LastWriteTime -Descending | Select Name 
            foreach($file in $fileRead)
            {
                 if($indx -gt 2){
                    $fileName=([String]$file.Name).Trim()
                    $tempPath=$FilePath+$fileName
                    if([System.IO.File]::Exists($tempPath)){
                        Remove-Item $tempPath -Force
                    }
                 }
               $indx++ 
        }
    }
}

Function Eg-DeleteCsvFiles(){
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$FilePath, 
        [Parameter(Mandatory=$true, Position=2)]
        [String]$Pattern
    )
    Process
    {
          $fileRead=Get-ChildItem -Path $FilePath |Where-Object {$_.Name -like $Pattern+'*.csv' }| Sort-Object LastWriteTime -Descending | Select Name 
            foreach($file in $fileRead)
            {
                    $fileName=([String]$file.Name).Trim()
                    $tempPath=$FilePath+$fileName
                    if([System.IO.File]::Exists($tempPath)){
                        Remove-Item $tempPath -Force
                    }
        }
    }
}


Function Eg-GetCont(){
	[CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$Nickname,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$TstName
    )

    Process
    {
        $tstInputs=@($Nickname,$TstName)
	    $egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        if($tstInputs.Length -eq 2){   
            $arg1='-jar '+$egurkhaPath+'\lib\GetCont.jar'
            $val=$egurkhaPath+'\lib\'+$tstInputs[0]+$tstInputs[1]+'_GetCont.log'
            $strVal=$arg1+' '+$tstInputs
            $fpath=$egurkhaPath+'\JRE\bin\java.exe'
            $null=Start-Process -FilePath $fpath -ArgumentList $strVal -WindowStyle Hidden -RedirectStandardOutput $val -Wait -PassThru
            
        }
        return $val
    }
}


Function Eg-GetAzureEnv(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$UserName,
        [String]$subject
    )
    Process
    {
        if($subject -eq '' -or $subject -eq $null){
            $subject='O365_AzureEnvironment'
        }
		$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        $usrDns=$UserName.Substring($UserName.LastIndexOf('.')+1)

        $azureEnv=''
        $tstIniPath=$egurkhaPath+'\agent\config\eg_tests.ini'
        $getAzureEnv=get-content -Path $tstIniPath
        $isFound=$false
        for($i=0;$i -lt $getAzureEnv.Length;$i++ ){
            if($getAzureEnv[$i].StartsWith('['+$subject)){ 
                $i++
                while($true){
                    try{
                        $azureEnvArr=$getAzureEnv[$i].Split('=')
                        if($usrDns -eq $azureEnvArr[0]){
                            $azureEnv=$azureEnvArr[1]
                            $isFound=$true
                            break;    
                        }
                    }catch{$isFound=$true;break;}
                    $i++  
                }
            }
        if($isFound){break;}
        }
        if($azureEnv -eq ''){
            $azureEnv='AzureCloud,https://outlook.office365.com/powershell-liveid/,smtp.office365.com,https://login.microsoftonline.com,O365Default' 
        }
        return $azureEnv
    }
}



Function Eg-ConvertTime
{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$Time
    )
    Process
    {
        if($Time -eq '' -or $Time -eq $null){
            return ''
        }
        [DateTime]$Time=$Time
		$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        $path=$egurkhaPath+'\agent\SBO\SBODataFile.ini'
        try{$tests=Get-content -Path $path}catch{}
        if($tests -eq $null -or $tests -eq ""){
            if(!(Test-Path -Path $path )){ New-Item -ItemType file -Path $path }
            $text='[SBO_ConvertTimeZone]'
            Add-Content $path -Value $text
            $text=';Dateline Standard Time,UTC-11,Hawaiian Standard Time,Alaskan Standard Time,US Mountain Standard Time,Pacific Standard Time,Pacific Standard Time (Mexico),Central America Standard Time,     Canada Central Standard Time,Mountain Standard Time (Mexico),Mountain Standard Time,SA Pacific Standard Time,    Central Standard Time, Central Standard Time (Mexico),Venezuela Standard Time,Central Brazilian Standard Time,Pacific SA Standard Time,SA Western Standard Time,    Eastern Standard Time, Paraguay Standard Time,  US Eastern Standard Time,   SA Eastern Standard Time,Montevideo Standard Time,Bahia Standard Time,Argentina Standard Time,Atlantic Standard Time,E. South America Standard Time,Newfoundland Standard Time,    Mid-Atlantic Standard Time,UTC-02,Greenland Standard Time,Cape Verde Standard Time,UTC,Greenwich Standard Time,Azores Standard Time, Morocco Standard Time,W. Central Africa Standard Time,GMT Standard Time ,South Africa Standard Time,Namibia Standard Time,Egypt Standard Time,Libya Standard Time,Central Europe Standard Time,W. Europe Standard Time,Romance Standard Time,Central European Standard Time,Israel Standard Time,Jordan Standard Time,Arabic Standard Time, E. Africa Standard Time,Arab Standard Time,Kaliningrad Standard Time,Syria Standard Time, Middle East Standard Time,   GTB Standard Time ,Turkey Standard Time, FLE Standard Time ,E. Europe Standard Time,Iran Standard Time, Mauritius Standard Time,Georgian Standard Time,Caucasus Standard Time,Arabian Standard Time,   Russian Standard Time, Afghanistan Standard Time,     Pakistan Standard Time,West Asia Standard Time,Azerbaijan Standard Time,Sri Lanka Standard Time,India Standard Time,Nepal Standard Time,Ekaterinburg Standard Time,Bangladesh Standard Time,Central Asia Standard Time,Myanmar Standard Time,N. Central Asia Standard Time,SE Asia Standard Time,   W. Australia Standard Time,Taipei Standard Time,Ulaanbaatar Standard Time,China Standard Time,North Asia Standard Time,Singapore Standard Time,Korea Standard Time,Tokyo Standard Time,North Asia East Standard Time,AUS Central Standard Time,Cen. Australia Standard Time,Tasmania Standard Time,Yakutsk Standard Time,West Pacific Standard Time, E. Australia Standard Time,AUS Eastern Standard Time,Vladivostok Standard Time,Central Pacific Standard Time,     Fiji Standard Time,Magadan Standard Time,UTC+12,Tonga Standard Time,Kamchatka Standard Time,New Zealand Standard Time,Samoa Standard Time'
            $text | Add-Content $path
            $text='ConvertTimeZoneFrom=Pacific Standard Time'
            $text | Add-Content $path
            $text='ConvertTimeZoneTo='+( ([TimeZoneInfo]::Local | select ID).ID )
            $text | Add-Content $path
        }
        $toTimeZone=''
        $firstEntry=$false
        foreach($testsini in $tests){
            if($testsini -eq '[SBO_ConvertTimeZone]'){
                $firstEntry=$true
            }
            elseif($testsini -eq $null){
                $firstEntry=$false
            }
            if($firstEntry){
                if($testsini -ne '[SBO_ConvertTimeZone]' -and $testsini -cnotcontains ';'){
                    if($testsini.StartsWith("ConvertTimeZoneFrom")){
                        $fromTimeZone= $testsini.Split("=")[1]
                    }
                    if($testsini.StartsWith("ConvertTimeZoneTo")){
                        $toTimeZone= $testsini.Split("=")[1]
                    }
                }
            }
        }

        $ToTimeZoneObj  = [system.timezoneinfo]::GetSystemTimeZones() | Where-Object {$_.id -eq $toTimeZone}    
        $oFromTimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById($fromTimeZone)
        $oToTimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById($toTimeZone)
        $utc = [System.TimeZoneInfo]::ConvertTimeToUtc($Time, $oFromTimeZone)
        $newTime = [System.TimeZoneInfo]::ConvertTime($utc, $oToTimeZone)
        return $newTime
    }
}

Function Eg-GetDomain(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$userName,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$Password,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$proxyUsr,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$proxyPass,
        [Parameter(Mandatory=$false, Position=5)]
        [boolean]$IsIntial,
        [Parameter(Mandatory=$false, Position=6)]
        [String]$Capabilities,
        [Parameter(Mandatory=$true, Position=7)]
        [String]$proxyserver,
        [Parameter(Mandatory=$false)]
        [String]$appDetails
    )
    Process
    {
        $Password=$Password.Replace("'","")
        $proxyPass=$proxyPass.Replace("'","")

        $azureVal=Eg-GetAzureEnv -UserName $userName
        $azureEnvArr=$azureVal.Split(',')
        $cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $Password -asplaintext -force)
        if(!$proxyserver.Contains('none')){
            if(!$proxyserver.Contains('http')){$proxyserver='http://'+$proxyserver;}
            [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy($proxyserver)
            if($proxyUsr -ne 'none' -and $proxyPass -ne 'none'){
                $proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $proxyUsr, $(convertto-securestring $proxyPass -asplaintext -force)	    
	            [system.net.webrequest]::defaultwebproxy.credentials =$proxyCred   #[System.Net.CredentialCache]::DefaultNetworkCredentials
	            [system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
            }
        }

        if($appDetails -and $appDetails -ne 'none'){
            $appDetailsArr=($appDetails).ToString() -Split ("~!~")
            $clientId=$appDetailsArr[0].Trim()
            $tenantName=$appDetailsArr[1].Trim()
            $thumbPrint=$appDetailsArr[2].Trim()
            $null=Connect-AzureAD -CertificateThumbprint $thumbPrint -ApplicationId $clientId -TenantId $tenantName
            $measure=Get-AzureADDomain |select * 
            if($IsIntial){
                $azureEnv= $measure|where{$_.IsInitial -eq $IsIntial}|select Name
                return $azureEnv.Name
            }
            elseif($Capabilities -ne $null -and $Capabilities -ne ''){
                $azureEnv= $measure|where{$_.SupportedServices -ccontains $Capabilities}|select Name
                return $azureEnv.Name
            }
            else{
                $azureEnv= $measure|select Name
                return $azureEnv.Name
            }
        }else{
        	Connect-MsolService -Credential $cred -AzureEnvironment $azureEnvArr[0]
		    $measure=Get-MsolDomain |select * 
	        if($IsIntial){
        	    $azureEnv= $measure|where{$_.IsInitial -eq $IsIntial}|select Name
	            return $azureEnv.Name
        	}
	        elseif($Capabilities -ne $null -and $Capabilities -ne ''){
            		$azureEnv= $measure|where{$_.Capabilities -ccontains $Capabilities}|select Name
            		return $azureEnv.Name
	        }
        	else{
            		$azureEnv= $measure|select Name
            		return $azureEnv.Name
		    }
        }
    }
}

Function Eg-O365Dcr(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$EncStr
    )
    Process
    {
        $encArr=$EncStr.Split(':')
        $count=$encArr.Count
        $j=124
        $c=$count
        $decStr=''
        $i=$count-1
        for($rr=0;$rr -lt $c ;$rr++){
            $str=$encArr[$rr].ToString()
            [int]$num=''
            if ([int]$str -le 0){
                $str=$str.Substring(1)
                $num=(([int]$str) * -1)
            }else{
                $num=$str
            }
            [int]$x=$num
            $k=$j-$x+$i*3
            $i--
            $byt=[System.BitConverter]::GetBytes($k)
            $dStr1=[System.Text.Encoding]::UTF8.GetString($byt)    
            $decStr=$decStr+$dStr1[0]
        }
        $dstr=''
        for($i=$decStr.Length;$i -ge 0;$i--){
            $dstr=$dstr+$decStr[$i]
        }
        return $dstr
    }
}

function Get-GraphClientSecret(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$InitialDomain    
    )
    Process
    {
		$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        try{
            $msGraphDir=$egurkhaPath+"\agent\O365\MsGraph"
            $keyFileNam = '\GraphDetailsKey.dat'
            $unProtPath= $msGraphDir+'\GraphDetails.dat'
            $kvalue= Get-Content -Path $msGraphDir$keyFileNam
            $null=Unprotect-File $unProtPath -Algorithm AES -KeyAsPlainText $kvalue -DstSuffix '.txt'
            $graphDtls=$msGraphDir+"\GraphDetails.txt"
            $GetInput = Get-Content -Path $graphDtls
        }catch{
            Write-Error -Message "File not found. The $GetInput location does not contain GraphDetails "
        }
        $flag=$false
        foreach($inp in $GetInput){
            if($inp.StartsWith('[') -and $inp -match $InitialDomain){
                $flag=$true
            }
            if($flag){
                if($inp.Contains("client_id")){
                    $appId =$inp.ToString().Substring($inp.IndexOf('~')+1)
                }
                if($inp.Contains("client_secret")){
                    $appSecret =$inp.ToString().Substring($inp.IndexOf('~')+1)
                    $flag=$false
                }
            }
        }
        $clntSecrtArr=@{}
        if($appId -ne $null -and $appId -ne ''){  
            $clntSecrtArr[0]=$appId.ToString().Trim()
            $clntSecrtArr[1]=$appSecret.ToString().Trim() 
            if([System.IO.File]::Exists($graphDtls)){
                Remove-Item -Path $graphDtls     
            }
        }
        return $clntSecrtArr
    }
}

function Check-WriteFile{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true, Position=1)]
        [String]$rptPath,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$srchWrd,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$mTimInMin
    )
    Process
    {  
        #$rptPath='C:\eGurkha\agent\EXO\eGinnovations435'
        $leafPath=$rptPath+'\Ticks.log'
        $tic=(Get-Date).Ticks

        if(!(Test-Path -Path $rptPath)){
            $null=New-Item -ItemType directory -Path $rptPath
        }

        if(Test-Path $leafPath -PathType Leaf){
            $ticLines=Get-Content -Path $leafPath
            $notFind=$true
            foreach($line in $ticLines){
                if($line.StartsWith($srchWrd)){
                    $notFind=$false
                    $lstTic=[long]$line.Replace($srchWrd+'-','')
                    $lstTicks=(Get-Date $lstTic).Ticks
                    $lstTicks=$lstTicks+([System.TimeSpan]::FromMinutes($mTimInMin)).Ticks
                    $curTicks=(Get-Date).Ticks
                    if($curTicks -ge $lstTicks){
                        $replaceCnt=$srchWrd+'-'+$curTicks
                        (Get-Content $leafPath).replace($line, $replaceCnt) | Set-Content $leafPath -Force
                        return $true
                    }else{
                        return $false
                    }
                }
            }
            if($notFind){
                $srchWrd+'-'+$tic|Add-Content -Path $leafPath -Force
                return $true
            }
        }else{
            #$null=New-Item -ItemType File -Path $leafPath
            $srchWrd+'-'+$tic|Add-Content -Path $leafPath -Force
            return $true
        }
    }
}


Function Get-SuperSetNDomains(){
    [CmdletBinding()]
    Param(
    [Parameter(Mandatory=$true, Position=1)]
        [String]$username,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$password, 
        [Parameter(Mandatory=$true, Position=3)]
        [String]$rptName,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$proxyserverip,
        [Parameter(Mandatory=$true, Position=5)]
        [String]$proxyUsr,
        [Parameter(Mandatory=$true, Position=6)]
        [String]$proxyPass,
        [Parameter(Mandatory=$false)]
        [String]$lastwritTim,
        [Parameter(Mandatory=$false)]
        [String]$appDetails
    )
     process
    {
		$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        $iniDir=$egurkhaPath+'\agent\config'
        $eg_AgentsIni=$iniDir+'\eg_agents.ini'
        $o365_DomainsIni=$iniDir+'\eg_0365Domains.ini'
        $o365_DomainsIni_tmp=$iniDir+'\eg_0365Domains_tmp.ini'

        $rptNamArr=$rptName.Split('_')
        $lockNam=$rptNamArr[0]
        $suffixNam='_'+$rptNamArr[1]
        $chkNam=$rptName

        $o365dmnsHash=@{}
        $eg_AgntIniLns=get-content -Path $eg_AgentsIni
        foreach($line in $eg_AgntIniLns){
            $cmpntChkStr=''
            if($line -match $suffixNam -and $line -like '*-Lookup_Domain*' -and $line -notlike '*-Lookup_Domain $unconfigured*'){ # $line -match '-Lookup_Domain'){
                $nickName=''
                $chkNum=$line.IndexOf('=-manual')
                if($chkNum -eq -1){
                    $chkNum=$line.IndexOf('=-auto')
                }
                $nickStr=$line.Substring(0,$chkNum)
                $nickName=$nickStr.Substring($nickStr.LastIndexOf(':')+1 )
                if($cmpntChkStr -notmatch $nickName){
                    $dmnStr=$line.Substring($line.IndexOf('Lookup_Domain '))
                    $dmnStr=$dmnStr.Replace('Lookup_Domain ','').Trim()
                    $inputDomains=$dmnStr.Substring(0,$dmnStr.IndexOf(' '))
                    $inputDomains=$inputDomains.Replace('|',',')
                    try{
                        $azureVal=Eg-GetAzureEnv -UserName $username
                        $azureEnvArr=$azureVal.Split(',')

                        $credential = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $username, $(convertto-securestring $password -asplaintext -force)
                        if($proxyserverip -notmatch 'none'){
                            if($proxyserverip -notmatch 'http'){$proxyserverip='http://'+$proxyserverip}
	                        [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy($proxyserverip)
							if($proxyUsr -ne 'none' -and $proxyPass -ne 'none'){
								$proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $proxyUsr, $(convertto-securestring $proxyPass -asplaintext -force)
								[System.Net.WebRequest]::DefaultWebProxy.Credentials = $proxyCred	
								[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
							}
                        }
                        if($appDetails -and $appDetails -ne 'none'){
                            $appDetailsArr=($appDetails).ToString() -Split ("~!~")
                            $clientId=$appDetailsArr[0].Trim()
                            $tenantName=$appDetailsArr[1].Trim()
                            $thumbPrint=$appDetailsArr[2].Trim()
                            $null=Connect-AzureAD -CertificateThumbprint $thumbPrint -ApplicationId $clientId -TenantId $tenantName
                            $measures=Get-AzureADDomain |select * 
                            $supersetNam=$measures | where {$_.IsInitial -eq $true}
                            $sprsetNam=$supersetNam.Name.Replace('.onmicrosoft.com','')
                            if(!$o365dmnsHash.ContainsKey($nickName)){
                                $o365dmnsHash.Add($nickName,$inputDomains+'~'+$sprsetNam)
                            }
                        }else{
                            Connect-MsolService -Credential $credential -AzureEnvironment $azureEnvArr[0]
                            $measures=Get-MsolDomain |select *
                            $supersetNam=$measures | where {$_.IsInitial -eq $true}
                            $sprsetNam=$supersetNam.Name.Replace('.onmicrosoft.com','')
                            if(!$o365dmnsHash.ContainsKey($nickName)){
                                $o365dmnsHash.Add($nickName,$inputDomains+'~'+$sprsetNam)
                            }
                        }
                    }
                    catch{
                        continue
                    }
                    $cmpntChkStr+='~'+$nickNam
                }
            }
        }
        if($lastwritTim -ne $null -and $lastwritTim -ne ''){  
            $needToWrite=@()
            $needToWrite+='['+$lastwritTim+']'
            $cntArr= Get-Content -path $o365_DomainsIni
            for($i=1;$i -lt $cntArr.Length;$i++){
                if($o365dmnsHash[$chkNam] -ne $null -and $o365dmnsHash[$chkNam] -ne ''){
                    $needToWrite+=$chkNam+'~'+$o365dmnsHash[$chkNam]
                }else{
                    $needToWrite+=$cntArr[$i]
                }
            } 
            foreach($line in $needToWrite){
               $line |Add-Content -Path $o365_DomainsIni_tmp
            } 
            try{
                handleThreadLock -setLock -lockName $lockNam
            }catch{Throw "Failed to set lock!"}
 
            try{
                if([System.IO.File]::Exists($o365_DomainsIni_tmp) -eq 'True'){
                    if([System.IO.File]::Exists($o365_DomainsIni) -eq 'True'){
                        Remove-Item $o365_DomainsIni 
                    }
                    Rename-Item -Path $o365_DomainsIni_tmp -NewName 'eg_0365Domains.ini'  
                }   
            }finally{
                handleThreadLock -releaseLock
            }                   
        }
        return $o365dmnsHash
    }
}

function handleThreadLock(){
    Param(
        [switch]$setLock,
        [switch]$releaseLock,
        [string]$lockName,
        [int]$timeOut=600
    )
    if($setLock){
        #register a thread lock
        $script:threadLock = New-Object System.Threading.Mutex($false, $lockName)
        $waited = 0
        while($true){
            try{$lockState = $script:threadLock.WaitOne(1000)}catch{$lockState=$False}
            if($lockState){
                break
            }else{
                $waited+=1
                if($waited -gt $timeOut){
                    Throw "failed to get a thread within $timeOut seconds!"
                }
            }
        }
    }  
    if($releaseLock){
        #release a thread lock
        if($script:threadLock.WaitOne()){
            [void]$script:threadLock.ReleaseMutex()
        }
    }  
}

Function Eg-O635Domains(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$username,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$password,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$rptNam, 
        [Parameter(Mandatory=$true, Position=4)]
        [String]$proxyserverip,
        [Parameter(Mandatory=$true, Position=5)]
        [String]$proxyUsr,
        [Parameter(Mandatory=$true, Position=6)]
        [String]$proxyPass,
        [Parameter(Mandatory=$false)]
        [String]$appDetails
        
    )
    Process
    { 
        try{
            handleThreadLock -setLock -lockName $rptNam
        }catch{Throw "Failed to set lock!"}
        try{
            $o365DmnsHash=@{}
	    	$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
            $iniDir=$egurkhaPath+'\agent\config'
            $eg_AgentsIni=$iniDir+'\eg_agents.ini'
            $o365_DomainsIni=$iniDir+'\eg_0365Domains.ini'

            $lastWritTim=(Get-Item -Path $eg_AgentsIni).LastWriteTime.Ticks
            if(Test-Path $o365_DomainsIni -PathType Leaf){
                $dmnLines=get-content -Path $o365_DomainsIni
                $dmnLstWritTim=$dmnLines[0].ToString().Replace('[','')
                $dmnLstWritTim=$dmnLstWritTim.Replace(']','')
                if($dmnLstWritTim -ne $lastWritTim){
                    $o365DmnsHash= Get-SuperSetNDomains -username $username -password $password -rptName $rptNam -proxyserverip $proxyserverip -proxyUsr $proxyUsr -proxyPass $proxyPass -lastwritTim $lastWritTim -appDetails $appDetails
                }else{
                    $arr=Get-Content -path $o365_DomainsIni
                    for($i=1;$i -lt $arr.Length;$i++ ){
                       $spltArr=$arr[$i].Split('~')
                       $o365DmnsHash.Add($spltArr[0],$spltArr[1]+'~'+$spltArr[2])
                    }
                }
            }
            else{
                $o365DmnsHash=Get-SuperSetNDomains -username $username -password $password -rptName $rptNam -proxyserverip $proxyserverip -proxyUsr $proxyUsr -proxyPass $proxyPass -lastwritTim '' -appDetails $appDetails
                if($o365DmnsHash.Count -ne 0){
                    '['+$lastWritTim+']'|Add-Content -Path $o365_DomainsIni
                    foreach($key in $o365DmnsHash.Keys){
                       $key+'~'+$o365DmnsHash[$key]|Add-Content -Path $o365_DomainsIni
                    }
                }
            }
            return $o365DmnsHash
        }
        finally{
            handleThreadLock -releaseLock
        } 
    }
}

Function Eg-GetINIContent(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$Path,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$Subject,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$Key,
        [Parameter(Mandatory=$false, Position=4)]
        [String]$Type
    )
    Process
    {
        $res=''
        $isExist=$false
        if($Type -ne $null -and $Type -ne ''){
            $lines=get-content -Path $Path -Encoding $Type
        }else{
            $lines=get-content -Path $Path
        }
        foreach($line in $lines){
            if($isExist){
                if($line.StartsWith($Key)){
                    $res=($line.Split('=')[1]).ToString()
                    break;
                }
            }
            if($line.StartsWith('['+$Subject)){
                $isExist=$true
            }
        }
        return $res
    }
}

Function Domains-ReadFrmINI(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$ps1FileName,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$RptName,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$ComponentName,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$EncType
    )

    Process
    {
		$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        $iniDir=$egurkhaPath+'\agent\O365'
        $teams_DomainIni=$iniDir+'\eg_O365Domains.ini'
        $ticksArr=@()
        if(Test-Path $teams_DomainIni -PathType Leaf){
            $tmDmnLns=get-content -Path $teams_DomainIni -Encoding $EncType
            $isRead=$false
            for($i=0;$i -lt $tmDmnLns.Length;$i++){
                if($isRead -and $tmDmnLns[$i].StartsWith($ps1FileName) -and $tmDmnLns[$i] -match $RptName){
                    $lstTickStr=$tmDmnLns[$i].Replace(($ps1FileName+'='),'')
                    $ticksArr=$lstTickStr.Split('~')
                    break;
                } 
                if($tmDmnLns[$i].StartsWith('['+$ComponentName)){
                    $isRead=$true
                }
            }
        }
        return $ticksArr
    }
}


Function Domains-WriteToINI(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$ps1FileName,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$RptNam,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$SfolderNam,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$ticks,
        [Parameter(Mandatory=$true, Position=5)]
        [String]$componentNam,
        [Parameter(Mandatory=$true, Position=6)]
        [String]$encTyp

    )

    Process
    {
		$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
        $iniDir=$egurkhaPath+'\agent\O365'
        $teams_DomainIni=$iniDir+'\eg_O365Domains.ini'
        $teams_DomainIni_tmp=$iniDir+'\eg_O365Domains_tmp.ini'

        if(!(Test-Path $teams_DomainIni -PathType Leaf)){
            $null=New-Item -ItemType File -Path $teams_DomainIni
        }

        $tmDmnLns=get-content -Path $teams_DomainIni -Encoding $encTyp
        $isRead=$false;$isFindCntnt=$false;$isChangFldr=$false;
        $cntnt=''
        for($i=0;$i -lt $tmDmnLns.Length;$i++){     
            if($isRead -and $tmDmnLns[$i].StartsWith($ps1FileName) -and $tmDmnLns[$i] -match $SfolderNam){
                $isFindCntnt=$true
                $inputStr=$tmDmnLns[$i].Replace(($ps1FileName+'='),'')
                $old_Rptnam=$inputStr.Split('~')[0]
                if($old_Rptnam.Length -ne 0){
                    if($old_Rptnam -match $RptNam){
                        $new_Rptnam=$old_Rptnam
                    }else{
                        $new_Rptnam=$old_Rptnam+'#'+$RptNam
                    } 
                }else{
                    $new_Rptnam=$RptNam
                }
                $cntnt=$ps1FileName+'='+$new_Rptnam+'~'+$SfolderNam+'~'+$ticks       
            }elseif($isRead -and $isFindCntnt -eq $false -and  $tmDmnLns[$i].StartsWith($ps1FileName) -and $tmDmnLns[$i] -notmatch $SfolderNam){
                $isFindCntnt=$true
                $addCFCntnt=$ps1FileName+'='+$RptNam+'~'+$SfolderNam+'~'+$ticks
                $addCFCntnt|Add-Content -Path $teams_DomainIni_tmp -Encoding $encTyp
                $cntnt=$tmDmnLns[$i]
            }else{
                $cntnt=$tmDmnLns[$i]
            } 
            if($isFindCntnt -eq $false -and $isRead -eq $true -and $tmDmnLns[$i].StartsWith("[")){
                $addCntnt=$ps1FileName+'='+$RptNam+'~'+$SfolderNam+'~'+$ticks
                $addCntnt|Set-Content -Path $teams_DomainIni_tmp -Encoding $encTyp
            }
            if($tmDmnLns[$i] -eq ('['+$componentNam+']')){
                $cntnt=$tmDmnLns[$i]
                $isRead=$true
            }
            $cntnt| Out-File $teams_DomainIni_tmp -Append -Encoding utf8
            if(!$isFindCntnt -and $i -eq $tmDmnLns.Length-1){
                $addCntnt=$ps1FileName+'='+$RptNam+'~'+$SfolderNam+'~'+$ticks
                $addCntnt | Add-Content -Path $teams_DomainIni_tmp -Encoding $encTyp
            }
        }
        if($isRead -eq $false){
            if($tmDmnLns.Length -eq 0){
                '['+$componentNam+']'|Add-Content -Path $teams_DomainIni -Encoding $encTyp
                $str=$ps1FileName+'='+$RptNam+'~'+$SfolderNam+'~'+$ticks
                $str|Add-Content -Path $teams_DomainIni -Encoding $encTyp
            }else{
                Get-Content $teams_DomainIni -Encoding $encTyp | Set-Content -Path $teams_DomainIni_tmp -Encoding $encTyp
                '['+$componentNam+']'|Add-Content -Path $teams_DomainIni_tmp
                $str=$ps1FileName+'='+$RptNam+'~'+$SfolderNam+'~'+$ticks
                $str|Add-Content -Path $teams_DomainIni_tmp -Encoding $encTyp
            }
        }

        #ThreadLock
        try{
            handleThreadLock -setLock -lockName $RptNam
        }catch{Throw "Failed to set lock!"}
        try{     
            if([System.IO.File]::Exists($teams_DomainIni_tmp) -eq 'True'){
                if([System.IO.File]::Exists($teams_DomainIni) -eq 'True'){
                    Remove-Item $teams_DomainIni 
                }
                Rename-Item -Path $teams_DomainIni_tmp -NewName 'eg_O365Domains.ini'  
            }           
        }finally{
            handleThreadLock -releaseLock
        }

    }
}

Function Domains-GetSuperset(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$UserName,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$Password,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$ProxyServerIP,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$ProxyUser,
        [Parameter(Mandatory=$true, Position=5)]
        [String]$ProxyPassword,
        [Parameter(Mandatory=$false)]
        [String]$appDetails
    )

    Process
    {
        Try{
            $azureVal=Eg-GetAzureEnv -UserName $UserName
            $azureEnvArr=$azureVal.Split(',')
            $credential = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $UserName, $(convertto-securestring $Password -asplaintext -force)
            if(!$ProxyServerIP.ToString().ToLower().Contains('none')){
                if($ProxyServerIP -notcontains 'http'){$proxyserver='http://'+$ProxyServerIP}else{$proxyserver=$ProxyServerIP}
                [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy($proxyserver)
            }
            if($ProxyUser -ne 'none' -and $ProxyPassword -ne 'none'){
	            $proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $ProxyUser, $(convertto-securestring $ProxyPassword -asplaintext -force)
	            [System.Net.WebRequest]::DefaultWebProxy.Credentials = $proxyCred	
	            [system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
            }
            if($appDetails -and $appDetails -ne 'none'){
                $appDetailsArr=($appDetails).ToString() -Split ("~!~")
                $clientId=$appDetailsArr[0].Trim()
                $tenantName=$appDetailsArr[1].Trim()
                $thumbPrint=$appDetailsArr[2].Trim()
                $null=Connect-AzureAD -CertificateThumbprint $thumbPrint -ApplicationId $clientId -TenantId $tenantName
                $measures=Get-AzureADDomain |select * 
                $supersetNam=$measures | where {$_.IsInitial -eq $true}
                $sprsetNam=$supersetNam.Name.Replace('.onmicrosoft.com','')
                return $sprsetNam
            }else{
                Connect-MsolService -Credential $credential -AzureEnvironment $azureEnvArr[0] -ErrorAction SilentlyContinue
                $measures=Get-MsolDomain -ErrorAction SilentlyContinue |select * 
                $supersetNam=$measures | where {$_.IsInitial -eq $true}
                $sprsetNam=$supersetNam.Name.Replace('.onmicrosoft.com','')
                return $sprsetNam
            }
        }
        Catch{
            return ''
        }
    }
}

Function Eg-ParseExact(){
	[CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$DateStr,
        [Parameter(Mandatory=$true, Position=2)]
        [String]$DateTimeFormat,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$TimeFormat,
        [Parameter(Mandatory=$true, Position=4)]
        [String]$HourFrmt
        
    )
     Process
    {
        $dat=''
        if($DateStr.Length -gt 11){
	    	$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
            $langPath=$egurkhaPath+'\agent\config\O365_lang.ini'
            $encTyp=Eg-GetINIContent -Path $langPath -Subject 'File_Type' -Key 'encoding'
            $am_Format=Eg-GetINIContent -Path $langPath -Subject 'TimeFormats' -Key 'AM' -Type $encTyp
            $pm_Format=Eg-GetINIContent -Path $langPath -Subject 'TimeFormats' -Key 'PM' -Type $encTyp
            if($TimeFormat -match 'tt' -and ($DateStr -notmatch $am_Format -and $DateStr -notmatch $pm_Format) -and $HourFrmt -ne 'none'){
                $DateStr=$DateStr.Trim()+' '+$HourFrmt
            }
        }
        $cultInfo=(Get-Culture).Name
        $dat=[DateTime]::ParseExact($DateStr,$DateTimeFormat,[cultureinfo]::GetCultureInfo($cultInfo),[System.Globalization.DateTimeStyles]::None)
        return $dat
    }
}

function Eg-RemoveGraphcsvFiles(){
	[CmdletBinding()]
    Param(
        [String]$rmvPath
    )
    Process{
        Try{  
            $rmvFile = [System.IO.FileInfo]$rmvPath
            $rmvDir=$rmvFile.DirectoryName
            $str=($rmvFile.BaseName).Substring(0,5)
            $srchNam=$str+(($rmvFile.BaseName).Replace($str,'') -replace "[0-9]","")
            Get-ChildItem -Path $rmvDir |Where-Object {$_.Name -like $srchNam+'*.csv'}|ForEach-Object{
                $path=$rmvDir+'\'+$_.Name
                if([System.IO.File]::Exists($path)){
                    Remove-Item -Path $path
                }
            }
        }Catch{
            $excepMsg='[GetDatnKeyFiles] Exception Occured in -- [Line Number] '+$_.InvocationInfo.ScriptLineNumber+' -- '+$_.Exception
            Write-Error $excepMsg
        }
    }
}

Export-ModuleMember -Function Eg-InvokeGraphUrl
Export-ModuleMember -Function Eg-WriteFile
Export-ModuleMember -Function Eg-ReadFile
Export-ModuleMember -Function Eg-DeleteFiles
Export-ModuleMember -Function Eg-DeleteCsvFiles
Export-ModuleMember -Function Eg-GetCont
Export-ModuleMember -Function Eg-GetAzureEnv
Export-ModuleMember -Function Eg-GetDomain
Export-ModuleMember -Function Eg-ConvertTime
Export-ModuleMember -Function Eg-O365Dcr
#Export-ModuleMember -Function Get-GraphClientSecret
Export-ModuleMember -Function Eg-O635Domains
Export-ModuleMember -Function Get-SuperSetNDomains
Export-ModuleMember -Function Check-WriteFile
Export-ModuleMember -Function Eg-WriteLog
Export-ModuleMember -Function Eg-GetINIContent
Export-ModuleMember -Function Domains-ReadFrmINI
Export-ModuleMember -Function Domains-WriteToINI
Export-ModuleMember -Function Domains-GetSuperset
Export-ModuleMember -Function Eg-ParseExact
Export-ModuleMember -Function Eg-RemoveGraphcsvFiles
