DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1

$allTrainableClassifiers = @(
    [PSCustomObject]@{ Name = 'Actuary reports'; Id = 'b27df2ee-fd14-4ce9-b02f-4070a5d68132' }
    [PSCustomObject]@{ Name = 'Agreements'; Id = '7f12e403-5335-4da8-a91e-6c2210b7a2b1' }
    [PSCustomObject]@{ Name = 'Asset Management'; Id = '716fb550-90cd-493b-b29b-ceed41ee8a6f' }
    [PSCustomObject]@{ Name = 'Bank statement'; Id = 'f426bd16-e42e-4397-824b-f17dedc5bb1c' }
    [PSCustomObject]@{ Name = 'Budget'; Id = '6f207592-f71e-4b4f-8c07-ebc4bd4965b9' }
    [PSCustomObject]@{ Name = 'Business Context'; Id = '08b772df-bf93-457f-be23-b5cbf02005fd' }
    [PSCustomObject]@{ Name = 'Business plan'; Id = '693f8221-ae4e-4612-80f5-746efee167c3' }
    [PSCustomObject]@{ Name = 'Completion Certificates'; Id = 'b2580781-286b-4ad2-ab47-84e84ff331e5' }
    [PSCustomObject]@{ Name = 'Compliance policies'; Id = 'fdad8089-651b-4877-8b66-be105b2e57da' }
    [PSCustomObject]@{ Name = 'Construction specifications'; Id = 'bfde18ef-b4b9-4f30-9965-ef8d00861a2c' }
    [PSCustomObject]@{ Name = 'Control System and SCADA files'; Id = '59f1f471-687d-453b-a73e-0b0e9f350812' }
    [PSCustomObject]@{ Name = 'Corporate Sabotage'; Id = 'd88960c3-6101-43d9-9250-8c43c71d638a' }
    [PSCustomObject]@{ Name = 'Credit Report'; Id = '07ce7d30-690a-4a1c-a331-8df9c944f1ab' }
    [PSCustomObject]@{ Name = 'Customer Complaints'; Id = '8137d8fc-fb7a-40db-9009-284f962fde96' }
    [PSCustomObject]@{ Name = 'Customer Files'; Id = 'fdff9df2-03ba-4372-be97-82c0d2515118' }
    [PSCustomObject]@{ Name = 'Discrimination'; Id = 'a65c4ab6-a155-11eb-921c-6c0b84aa8ea5' }
    [PSCustomObject]@{ Name = 'Employee disciplinary action files'; Id = '769d56c1-e737-4fc1-8673-8c99bbe24a07' }
    [PSCustomObject]@{ Name = 'Employee Insurance files'; Id = 'fa982a9f-9454-4885-a2bf-94a155df2f33' }
    [PSCustomObject]@{ Name = 'Employee Pension Records'; Id = 'f9ae0bbc-a1e0-4b7e-a96a-eb60b26b4434' }
    [PSCustomObject]@{ Name = 'Employee Stocks and Financial Bond Records'; Id = 'a67b2b59-c5f0-4c66-a6c4-ca6973adfd94' }
    [PSCustomObject]@{ Name = 'Employment Agreement'; Id = '2a2baab7-b82c-4166-bbe4-55f9d3fd1129' }
    [PSCustomObject]@{ Name = 'Enterprise Risk Management'; Id = 'eed09aae-6f32-47c7-9c99-9d17bad48783' }
    [PSCustomObject]@{ Name = 'Environmental permits and clearances'; Id = '1b7d3e51-0ecf-41bd-9794-966c94a889ba' }
    [PSCustomObject]@{ Name = 'Facility Permits'; Id = '914c5379-9d05-47cb-98f0-f5a2be059b5a' }
    [PSCustomObject]@{ Name = 'factory Incident Investigation reports'; Id = '86186144-d507-4603-bac7-50b56ba05c70' }
    [PSCustomObject]@{ Name = 'Finance'; Id = '1771481d-a337-4dbf-8e64-af8da0cc3ee9' }
    [PSCustomObject]@{ Name = 'Finance policies and procedures'; Id = '6556c5eb-0819-4618-ba2e-59925925655e' }
    [PSCustomObject]@{ Name = 'Financial Audit Reports'; Id = 'b04b2a4e-22f8-4024-8adc-e2caaad1c2e2' }
    [PSCustomObject]@{ Name = 'Financial statement'; Id = 'c31bfef9-8045-4a35-88a3-74b8681615c2' }
    [PSCustomObject]@{ Name = 'Freight Documents'; Id = '785917ed-db01-43c7-8153-8a6fc393efa3' }
    [PSCustomObject]@{ Name = 'Garnishment'; Id = '65e827c3-f8e8-4bc8-b08c-c31e3132b832' }
    [PSCustomObject]@{ Name = 'Gifts \u0026 entertainment'; Id = '3b3d817a-9190-465b-af2d-9e856f894059' }
    [PSCustomObject]@{ Name = 'Health/Medical forms'; Id = '7cc60f30-9e96-4d51-b26f-3d7a9df56338' }
    [PSCustomObject]@{ Name = 'Healthcare'; Id = 'dcbada08-65bf-4561-b140-25d8fee4d143' }
    [PSCustomObject]@{ Name = 'HR'; Id = '11631f87-7ffe-4052-b173-abda16b231f3' }
    [PSCustomObject]@{ Name = 'Invoice'; Id = 'bf7df7c3-fce4-4ffd-ab90-26f6463f3a00' }
    [PSCustomObject]@{ Name = 'IP'; Id = '495fad07-d6e4-4da4-9c64-5b9b109a5f59' }
    [PSCustomObject]@{ Name = 'IT'; Id = '77a140be-c29f-4155-9dc4-c3e247e47560' }
    [PSCustomObject]@{ Name = 'IT Infra and Network Security Documents'; Id = 'bc55de38-cb72-43e6-952f-8422f584f229' }
    [PSCustomObject]@{ Name = 'Lease Deeds'; Id = '841f54ad-3e31-4ddd-aea0-e7f0cd6b3d18' }
    [PSCustomObject]@{ Name = 'Legal Affairs'; Id = 'ba38aa0f-8c86-4c73-87db-95147a0f4420' }
    [PSCustomObject]@{ Name = 'Legal Agreements'; Id = 'bee9cefb-88bd-410f-ab3e-67cab21cef46' }
    [PSCustomObject]@{ Name = 'Letter of Credits'; Id = 'fd85acd5-59dd-49b2-a4c3-df7075885a82' }
    [PSCustomObject]@{ Name = 'License agreement'; Id = 'b399eb17-c9c4-4205-951b-43f38eb8dffe' }
    [PSCustomObject]@{ Name = 'Loan agreements and offer letters'; Id = '5771fa57-34a1-48b3-93df-778b304daa54' }
    [PSCustomObject]@{ Name = 'M&A Files'; Id = 'eeffbf7c-fd04-40ef-a156-b37bf61832f7' }
    [PSCustomObject]@{ Name = 'Manufacturing batch records'; Id = '834b2353-509a-4605-b4f1-fc2172a0d97c' }
    [PSCustomObject]@{ Name = 'Marketing Collaterals'; Id = 'fcaa6d2a-601c-4bdc-947e-af1178a646ac' }
    [PSCustomObject]@{ Name = 'Meeting notes'; Id = 'e7ff9a9e-4689-4192-b927-e6c6bdf099fc' }
    [PSCustomObject]@{ Name = 'Money laundering'; Id = 'adbbb20e-b175-46e7-8ba2-cf3f3179d0ed' }
    [PSCustomObject]@{ Name = 'MoU Files (Memorandum of understanding)'; Id = 'cb37c277-4b88-49c6-81fb-2eeca8c52bb9' }
    [PSCustomObject]@{ Name = 'Network Design files'; Id = '12587d70-9596-4c21-b09f-f1abe9d6ca13' }
    [PSCustomObject]@{ Name = 'Non disclosure agreement'; Id = '8dfd10db-0c72-4be4-a4f2-f615fe7aeb1c' }
    [PSCustomObject]@{ Name = 'OSHA records'; Id = 'b11b771e-7dd1-4434-873a-d648a16e969e' }
    [PSCustomObject]@{ Name = 'Paystub'; Id = '31c11384-2d64-4635-9335-018295c64268' }
    [PSCustomObject]@{ Name = 'Personal Financial Information'; Id = '6901c616-5857-432f-b3da-f5234fa1d342' }
    [PSCustomObject]@{ Name = 'Procurement'; Id = '8fa64a47-6e77-4b4c-91a5-0f67525cebf5' }
    [PSCustomObject]@{ Name = 'Profanity'; Id = '4b0aa61d-37dc-4596-a1f1-fc5a5b21d56b' }
    [PSCustomObject]@{ Name = 'Project documents'; Id = 'e062df90-816c-47ca-8913-db647510d3b5' }
    [PSCustomObject]@{ Name = 'Quality assurance files'; Id = '97b1e0d3-7788-4dd4-bb18-48ea77796743' }
    [PSCustomObject]@{ Name = 'Quotation'; Id = '3882e681-c437-42d8-ac75-1f9b7481fe13' }
    [PSCustomObject]@{ Name = 'Regulatory Collusion'; Id = '911b7815-6883-4022-a882-9cbe9462f114' }
    [PSCustomObject]@{ Name = 'Resume'; Id = '14b2da41-0427-47e9-a11b-c924e1d05689' }
    [PSCustomObject]@{ Name = 'Safety Records'; Id = '938fb100-5b1f-4bbb-aba7-73d9c89d086f' }
    [PSCustomObject]@{ Name = 'Sales and revenue'; Id = '9d6b864d-28c6-4be3-a9d0-cd40434a847f' }
    [PSCustomObject]@{ Name = 'Software Product Development Files'; Id = '813aa6d8-0727-48d8-acb7-06e1819ee339' }
    [PSCustomObject]@{ Name = 'Source code'; Id = '8aef6743-61aa-44b9-9ae5-3bb3d77df535' }
    [PSCustomObject]@{ Name = 'Standard Operating Procedures and Manuals'; Id = '32f23ad4-2ca1-4495-8048-8dc567891644' }
    [PSCustomObject]@{ Name = 'Statement of Accounts'; Id = 'fe3676a6-0f5d-4990-bb46-9b2b31d7746a' }
    [PSCustomObject]@{ Name = 'Statement of Work'; Id = '611c95f9-b1ef-4253-8b36-d8ae19d02fb0' }
    [PSCustomObject]@{ Name = 'Stock manipulation'; Id = '1140cd79-ad87-4043-a562-c768acacc6ba' }
    [PSCustomObject]@{ Name = 'Strategic planning documents'; Id = '9332b317-2ca4-413a-b983-92a1bd88c6f3' }
    [PSCustomObject]@{ Name = 'Targeted Harassment'; Id = 'a02ddb8e-3c93-44ac-87c1-2f682b1cb78e' }
    [PSCustomObject]@{ Name = 'Tax'; Id = '9722b51a-f920-4a81-8390-b188a0692840' }
    [PSCustomObject]@{ Name = 'Threat'; Id = 'ef2edb64-6982-4648-b0ad-c0d8a861501b' }
    [PSCustomObject]@{ Name = 'Unauthorized disclosure'; Id = '839aecf8-c67b-4270-8aaf-378127b23b7f' }
    [PSCustomObject]@{ Name = 'Wire transfer'; Id = '05fc5ed0-58ef-4306-b65c-11b0a43895c2' }
    [PSCustomObject]@{ Name = 'Work Schedules'; Id = '25bb9d2d-a5b5-45b1-882e-b2581a183873' }
)

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [Parameter()]
        [System.String]
        $Comment,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $AdvancedSettings,

        [Parameter()]
        [System.String]
        $DisplayName,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $LocaleSettings,

        [Parameter()]
        [System.String]
        $ParentId,

        [Parameter()]
        [uint32]
        $Priority,

        [Parameter()]
        [System.String]
        $Tooltip,

        [Parameter()]
        [ValidateSet('Present', 'Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [ValidateSet('Left', 'Center', 'Right')]
        [System.String]
        $ApplyContentMarkingFooterAlignment,

        [Parameter()]
        [System.Boolean]
        $ApplyContentMarkingFooterEnabled,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingFooterFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingFooterFontSize,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingFooterMargin,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingFooterText,

        [Parameter()]
        [ValidateSet('Left', 'Center', 'Right')]
        [System.String]
        $ApplyContentMarkingHeaderAlignment,

        [Parameter()]
        [System.Boolean]
        $ApplyContentMarkingHeaderEnabled,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingHeaderFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingHeaderFontSize,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingHeaderMargin,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingHeaderText,

        [Parameter()]
        [System.Boolean]
        $ApplyWaterMarkingEnabled,

        [Parameter()]
        [System.String]
        $ApplyWaterMarkingFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyWaterMarkingFontSize,

        [Parameter()]
        [ValidateSet('Horizontal', 'Diagonal')]
        [System.String]
        $ApplyWaterMarkingLayout,

        [Parameter()]
        [System.String]
        $ApplyWaterMarkingText,

        [Parameter()]
        [ValidateSet('File, Email', 'Site, UnifiedGroup', 'PurviewAssets', 'Teamwork', 'SchematizedData')]
        [System.String[]]
        $ContentType,

        [Parameter()]
        [System.String]
        $EncryptionContentExpiredOnDateInDaysOrNever,

        [Parameter()]
        [System.Boolean]
        $EncryptionDoNotForward,

        [Parameter()]
        [System.Boolean]
        $EncryptionEncryptOnly,

        [Parameter()]
        [System.Boolean]
        $EncryptionEnabled,

        [Parameter()]
        [System.Int32]
        $EncryptionOfflineAccessDays,

        [Parameter()]
        [System.Boolean]
        $EncryptionPromptUser,

        [Parameter()]
        [System.String]
        $EncryptionProtectionType,

        [Parameter()]
        [System.String]
        $EncryptionRightsDefinitions,

        [Parameter()]
        [System.String]
        $EncryptionRightsUrl,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowAccessToGuestUsers,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowEmailFromGuestUsers,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowFullAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowLimitedAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionBlockAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionEnabled,

        [Parameter()]
        [ValidateSet('Public', 'Private', 'Unspecified')]
        [System.String]
        $SiteAndGroupProtectionPrivacy,

        [Parameter()]
        [ValidateSet('ExternalUserAndGuestSharing', 'ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', 'Disabled')]
        [System.String]
        $SiteAndGroupExternalSharingControlType,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance]
        $AutoLabelingSettings,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [System.String]
        $CertificatePath,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $CertificatePassword,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )

    Write-Verbose -Message "Getting configuration of Sensitivity Label for $Name"
    if ($Global:CurrentModeIsExport)
    {
        $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' `
            -InboundParameters $PSBoundParameters `
            -SkipModuleReload $true
    }
    else
    {
        $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' `
            -InboundParameters $PSBoundParameters
    }

    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    $nullReturn = $PSBoundParameters
    $nullReturn.Ensure = 'Absent'

    try
    {
        try
        {
            $label = Get-Label -Identity $Name -ErrorAction SilentlyContinue `
                -IncludeDetailedLabelActions
        }
        catch
        {
            throw $_
        }

        if ($null -eq $label)
        {
            Write-Verbose -Message "Sensitivity label $($Name) does not exist."
            return $nullReturn
        }
        else
        {
            $parentLabelID = $null
            if ($null -ne $label.ParentId)
            {
                $parentLabel = Get-Label -Identity $label.ParentId -IncludeDetailedLabelActions -ErrorAction 'SilentlyContinue'
                $parentLabelID = $parentLabel.Name
            }
            if ($null -ne $label.LocaleSettings)
            {
                $localeSettingsValue = Convert-JSONToLocaleSettings -JSONLocalSettings $label.LocaleSettings
            }
            if ($null -ne $label.Settings)
            {
                $advancedSettingsValue = Convert-StringToAdvancedSettings -AdvancedSettings $label.Settings
            }
            Write-Verbose "Found existing Sensitivity Label $($Name)"

            [Array]$labelActions = $label.LabelActions
            $actions = @()
            foreach ($labelAction in $labelActions)
            {
                $action = ConvertFrom-Json ($labelAction | Out-String)
                $actions += $action
            }

            $encryption = ($actions | Where-Object -FilterScript { $_.Type -eq 'encrypt' }).Settings
            $header = ($actions | Where-Object -FilterScript { $_.Type -eq 'applycontentmarking' -and $_.Subtype -eq 'header' }).Settings
            $footer = ($actions | Where-Object -FilterScript { $_.Type -eq 'applycontentmarking' -and $_.Subtype -eq 'footer' }).Settings
            $watermark = ($actions | Where-Object -FilterScript { $_.Type -eq 'applywatermarking' }).Settings
            $protectgroup = ($actions | Where-Object -FilterScript { $_.Type -eq 'protectgroup' }).Settings
            $protectsite = ($actions | Where-Object -FilterScript { $_.Type -eq 'protectsite' }).Settings

            $ApplyContentMarkingFooterTextValue = $null
            $footerText = ($footer | Where-Object -FilterScript { $_.Key -eq 'text' }).Value
            if ([System.String]::IsNullOrEmpty($footerText) -eq $false)
            {
                $ApplyContentMarkingFooterTextValue = $footerText.Replace('$', '`$')
            }

            $ApplyContentMarkingHeaderTextValue = $null
            $headerText = ($header | Where-Object -FilterScript { $_.Key -eq 'text' }).Value
            if ([System.String]::IsNullOrEmpty($headerText) -eq $false)
            {
                $ApplyContentMarkingHeaderTextValue = $headerText.Replace('$', '`$')
            }

            $ApplyWaterMarkingTextValue = $null
            $watermarkText = ($watermark | Where-Object -FilterScript { $_.Key -eq 'text' }).Value
            if ([System.String]::IsNullOrEmpty($watermarkText) -eq $false)
            {
                $ApplyWaterMarkingTextValue = $watermarkText.Replace('$', '`$')
            }

            $currentContentType = @()
            switch -Regex ($label.ContentType)
            {
                'File, Email'
                {
                    $currentContentType += 'File, Email'
                }
                'Site, UnifiedGroup'
                {
                    $currentContentType += 'Site, UnifiedGroup'
                }
                'PurviewAssets'
                {
                    $currentContentType += 'PurviewAssets'
                }
                'Teamwork'
                {
                    $currentContentType += 'Teamwork'
                }
                'SchematizedData'
                {
                    $currentContentType += 'SchematizedData'
                }
            }

            # Encryption
            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'disabled' }
            if ($null -ne $entry)
            {
                $encryptionEnabledValue = -not [Boolean]::Parse($entry.Value)
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'contentexpiredondateindaysornever' }
            if ($null -ne $entry)
            {
                $contentExpiredOnDateValue = $entry.Value
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'protectiontype' }
            if ($null -ne $entry)
            {
                $protectionTypeValue = $entry.Value
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'offlineaccessdays' }
            if ($null -ne $entry)
            {
                $offlineAccessDaysValue = $entry.Value
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'rightsdefinitions' }
            if ($null -ne $entry)
            {
                $EncryptionRightsDefinitionsValue = Convert-EncryptionRightDefinition -RightsDefinition $entry.Value
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'donotforward' }
            if ($null -ne $entry)
            {
                $encryptionDoNotForwardValue = [Boolean]::Parse($entry.Value)
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'encryptonly' }
            if ($null -ne $entry)
            {
                $encryptionEncryptOnlyValue = [Boolean]::Parse($entry.Value)
            }

            $entry = $encryption | Where-Object -FilterScript { $_.Key -eq 'promptuser' }
            if ($null -ne $entry)
            {
                $encryptionPromptUserValue = [Boolean]::Parse($entry.Value)
            }

            # Watermark
            $entry = $watermark | Where-Object -FilterScript { $_.Key -eq 'disabled' }
            if ($null -ne $entry)
            {
                $watermarkEnabledValue = -not [Boolean]::Parse($entry.Value)
            }

            # Watermark Footer
            $entry = $footer | Where-Object -FilterScript { $_.Key -eq 'disabled' }
            if ($null -ne $entry)
            {
                $footerEnabledValue = -not [Boolean]::Parse($entry.Value)
            }

            # Watermark Header
            $entry = $header | Where-Object -FilterScript { $_.Key -eq 'disabled' }
            if ($null -ne $entry)
            {
                $headerEnabledValue = -not [Boolean]::Parse($entry.Value)
            }

            # Site and Group
            $entry = $protectgroup | Where-Object -FilterScript { $_.Key -eq 'disabled' }
            if ($null -ne $entry)
            {
                $siteAndGroupEnabledValue = -not [Boolean]::Parse($entry.Value)
            }

            $entry = $protectgroup | Where-Object -FilterScript { $_.Key -eq 'allowaccesstoguestusers' }
            if ($null -ne $entry)
            {
                $siteAndGroupAccessToGuestUsersValue = [Boolean]::Parse($entry.Value)
            }

            $entry = $protectgroup | Where-Object -FilterScript { $_.Key -eq 'allowemailfromguestusers' }
            if ($null -ne $entry)
            {
                $siteAndGroupAllowEmailFromGuestUsers = [Boolean]::Parse($entry.Value)
            }

            $entry = $protectsite | Where-Object -FilterScript { $_.Key -eq 'allowfullaccess' }
            if ($null -ne $entry)
            {
                $siteAndGroupAllowFullAccess = [Boolean]::Parse($entry.Value)
            }

            $entry = $protectsite | Where-Object -FilterScript { $_.Key -eq 'allowlimitedaccess' }
            if ($null -ne $entry)
            {
                $siteAndGroupAllowLimitedAccess = [Boolean]::Parse($entry.Value)
            }

            $entry = $protectsite | Where-Object -FilterScript { $_.Key -eq 'blockaccess' }
            if ($null -ne $entry)
            {
                $siteAndGroupBlockAccess = [Boolean]::Parse($entry.Value)
            }

            # Auto Labelling Conditions
            $getConditions = $null
            if ([System.String]::IsNullOrEmpty($label.Conditions) -eq $false)
            {
                $currConditions = $label.Conditions | ConvertFrom-Json

                $getConditions = @{
                    Groups   = @()
                    Operator = ''
                }

                $operator = $currConditions.PSObject.Properties.Name
                $getConditions.Operator = $operator

                $autoApplyType = ''
                $policyTip = ''
                $groups = foreach ($group in $currConditions.$($operator))
                {
                    $grpObject = @{
                        Name     = ''
                        Operator = ''
                    }

                    $grpOperator = $group.PSObject.Properties.Name
                    $grpObject.Operator = $grpOperator

                    $grpName = ''
                    [array]$sensitiveInformationTypes = foreach ($item in $group.$grpOperator | Where-Object { $_.Key -eq 'CCSI' })
                    {
                        if ([String]::IsNullOrEmpty($grpName))
                        {
                            $grpName = ($item.Settings | Where-Object { $_.Key -eq 'groupname' }).Value
                        }

                        if ([String]::IsNullOrEmpty($policyTip))
                        {
                            $policyTip = ($item.Settings | Where-Object { $_.Key -eq 'policytip' }).Value
                        }

                        if ([String]::IsNullOrEmpty($autoApplyType))
                        {
                            $autoApplyType = ($item.Settings | Where-Object { $_.Key -eq 'autoapplytype' }).Value
                        }

                        $settingsObject = @{
                            name            = ($item.Settings | Where-Object { $_.Key -eq 'name' }).Value
                            confidencelevel = ($item.Settings | Where-Object { $_.Key -eq 'confidencelevel' }).Value
                            mincount        = ($item.Settings | Where-Object { $_.Key -eq 'mincount' }).Value
                            maxcount        = ($item.Settings | Where-Object { $_.Key -eq 'maxcount' }).Value
                        }

                        if ($null -ne ($item.Settings | Where-Object { $_.Key -eq 'classifiertype' }))
                        {
                            $settingsObject.classifiertype = ($item.Settings | Where-Object { $_.Key -eq 'classifiertype' }).Value
                        }

                        # return the settings object as output to the sensitiveInformationTypes array
                        $settingsObject
                    }

                    [array]$trainableClassifiers = foreach ($item in $group.$grpOperator | Where-Object { $_.Key -eq 'ContentMatchesModule' })
                    {
                        if ([String]::IsNullOrEmpty($grpName))
                        {
                            $grpName = ($item.Settings | Where-Object { $_.Key -eq 'groupname' }).Value
                        }

                        @{
                            name = ($item.Settings | Where-Object { $_.Key -eq 'name' }).Value
                            id   = $item.Value
                        }
                    }

                    $grpObject.Name = $grpName
                    $grpObject.SensitiveInformationType = $sensitiveInformationTypes
                    $grpObject.TrainableClassifier = $trainableClassifiers

                    # return the group object as output to the groups array
                    $grpObject
                }
                $getConditions.Groups = $groups
                if ([System.String]::IsNullOrEmpty($policyTip) -eq $false)
                {
                    $getConditions.PolicyTip = $policyTip
                }
                if ([System.String]::IsNullOrEmpty($autoApplyType) -eq $false)
                {
                    $getConditions.AutoApplyType = $autoApplyType
                }
                else
                {
                    $getConditions.AutoApplyType = 'Automatic'
                }
            }

            $result = @{
                Name                                           = $label.Name
                Comment                                        = $label.Comment
                ParentId                                       = $parentLabelID
                AdvancedSettings                               = $advancedSettingsValue
                DisplayName                                    = $label.DisplayName
                LocaleSettings                                 = $localeSettingsValue
                Priority                                       = $label.Priority
                Tooltip                                        = $label.Tooltip
                Credential                                     = $Credential
                ApplicationId                                  = $ApplicationId
                TenantId                                       = $TenantId
                CertificateThumbprint                          = $CertificateThumbprint
                CertificatePath                                = $CertificatePath
                CertificatePassword                            = $CertificatePassword
                Ensure                                         = 'Present'
                ApplyContentMarkingFooterAlignment             = ($footer | Where-Object { $_.Key -eq 'alignment' }).Value
                ApplyContentMarkingFooterEnabled               = $footerEnabledValue
                ApplyContentMarkingFooterFontColor             = ($footer | Where-Object { $_.Key -eq 'fontcolor' }).Value
                ApplyContentMarkingFooterFontSize              = ($footer | Where-Object { $_.Key -eq 'fontsize' }).Value
                ApplyContentMarkingFooterMargin                = ($footer | Where-Object { $_.Key -eq 'margin' }).Value
                ApplyContentMarkingFooterText                  = $ApplyContentMarkingFooterTextValue
                ApplyContentMarkingHeaderAlignment             = ($header | Where-Object { $_.Key -eq 'alignment' }).Value
                ApplyContentMarkingHeaderEnabled               = $headerEnabledValue
                ApplyContentMarkingHeaderFontColor             = ($header | Where-Object { $_.Key -eq 'fontcolor' }).Value
                ApplyContentMarkingHeaderFontSize              = ($header | Where-Object { $_.Key -eq 'fontsize' }).Value
                ApplyContentMarkingHeaderMargin                = ($header | Where-Object { $_.Key -eq 'margin' }).Value
                #TODO ADD HEADER PLACEMENT?
                ApplyContentMarkingHeaderText                  = $ApplyContentMarkingHeaderTextValue
                ApplyWaterMarkingEnabled                       = $watermarkEnabledValue
                ApplyWaterMarkingFontColor                     = ($watermark | Where-Object { $_.Key -eq 'fontcolor' }).Value
                ApplyWaterMarkingFontSize                      = ($watermark | Where-Object { $_.Key -eq 'fontsize' }).Value
                ApplyWaterMarkingLayout                        = ($watermark | Where-Object { $_.Key -eq 'layout' }).Value
                ApplyWaterMarkingText                          = $ApplyWaterMarkingTextValue
                ContentType                                    = $currentContentType
                EncryptionContentExpiredOnDateInDaysOrNever    = $contentExpiredOnDateValue
                EncryptionDoNotForward                         = $encryptionDoNotForwardValue
                EncryptionEncryptOnly                          = $encryptionEncryptOnlyValue
                EncryptionEnabled                              = $encryptionEnabledValue
                EncryptionOfflineAccessDays                    = $offlineAccessDaysValue
                EncryptionPromptUser                           = $encryptionPromptUserValue
                EncryptionProtectionType                       = $protectionTypeValue
                EncryptionRightsDefinitions                    = $EncryptionRightsDefinitionsValue
                EncryptionRightsUrl                            = ($encryption | Where-Object { $_.Key -eq 'doublekeyencryptionurl' }).Value
                SiteAndGroupProtectionAllowAccessToGuestUsers  = $siteAndGroupAccessToGuestUsersValue
                SiteAndGroupProtectionAllowEmailFromGuestUsers = $siteAndGroupAllowEmailFromGuestUsers
                SiteAndGroupProtectionPrivacy                  = ($protectgroup | Where-Object { $_.Key -eq 'privacy' }).Value
                SiteAndGroupProtectionAllowFullAccess          = $siteAndGroupAllowFullAccess
                SiteAndGroupProtectionAllowLimitedAccess       = $siteAndGroupAllowLimitedAccess
                SiteAndGroupProtectionBlockAccess              = $siteAndGroupBlockAccess
                SiteAndGroupProtectionEnabled                  = $siteAndGroupEnabledValue
                SiteAndGroupExternalSharingControlType         = ($protectsite | Where-Object { $_.Key -eq 'externalsharingcontroltype' }).Value
                AccessTokens                                   = $AccessTokens
                AutoLabelingSettings                           = $getConditions
            }

            return $result
        }
    }
    catch
    {
        New-M365DSCLogEntry -Message 'Error retrieving data:' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential

        return $nullReturn
    }
}

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [Parameter()]
        [System.String]
        $Comment,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $AdvancedSettings,

        [Parameter()]
        [System.String]
        $DisplayName,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $LocaleSettings,

        [Parameter()]
        [System.String]
        $ParentId,

        [Parameter()]
        [uint32]
        $Priority,

        [Parameter()]
        [System.String]
        $Tooltip,

        [Parameter()]
        [ValidateSet('Present', 'Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [ValidateSet('Left', 'Center', 'Right')]
        [System.String]
        $ApplyContentMarkingFooterAlignment,

        [Parameter()]
        [System.Boolean]
        $ApplyContentMarkingFooterEnabled,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingFooterFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingFooterFontSize,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingFooterMargin,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingFooterText,

        [Parameter()]
        [ValidateSet('Left', 'Center', 'Right')]
        [System.String]
        $ApplyContentMarkingHeaderAlignment,

        [Parameter()]
        [System.Boolean]
        $ApplyContentMarkingHeaderEnabled,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingHeaderFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingHeaderFontSize,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingHeaderMargin,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingHeaderText,

        [Parameter()]
        [System.Boolean]
        $ApplyWaterMarkingEnabled,

        [Parameter()]
        [System.String]
        $ApplyWaterMarkingFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyWaterMarkingFontSize,

        [Parameter()]
        [ValidateSet('Horizontal', 'Diagonal')]
        [System.String]
        $ApplyWaterMarkingLayout,

        [Parameter()]
        [System.String]
        $ApplyWaterMarkingText,

        [Parameter()]
        [ValidateSet('File, Email', 'Site, UnifiedGroup', 'PurviewAssets', 'Teamwork', 'SchematizedData')]
        [System.String[]]
        $ContentType,

        [Parameter()]
        [System.String]
        $EncryptionContentExpiredOnDateInDaysOrNever,

        [Parameter()]
        [System.Boolean]
        $EncryptionDoNotForward,

        [Parameter()]
        [System.Boolean]
        $EncryptionEncryptOnly,

        [Parameter()]
        [System.Boolean]
        $EncryptionEnabled,

        [Parameter()]
        [System.Int32]
        $EncryptionOfflineAccessDays,

        [Parameter()]
        [System.Boolean]
        $EncryptionPromptUser,

        [Parameter()]
        [System.String]
        $EncryptionProtectionType,

        [Parameter()]
        [System.String]
        $EncryptionRightsDefinitions,

        [Parameter()]
        [System.String]
        $EncryptionRightsUrl,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowAccessToGuestUsers,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowEmailFromGuestUsers,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowFullAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowLimitedAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionBlockAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionEnabled,

        [Parameter()]
        [ValidateSet('Public', 'Private', 'Unspecified')]
        [System.String]
        $SiteAndGroupProtectionPrivacy,

        [Parameter()]
        [ValidateSet('ExternalUserAndGuestSharing', 'ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', 'Disabled')]
        [System.String]
        $SiteAndGroupExternalSharingControlType,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance]
        $AutoLabelingSettings,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [System.String]
        $CertificatePath,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $CertificatePassword,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )

    Write-Verbose -Message "Setting configuration of Sensitivity label for $Name"

    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' `
        -InboundParameters $PSBoundParameters

    $label = Get-TargetResource @PSBoundParameters

    if (($SiteAndGroupProtectionAllowFullAccess -and $SiteAndGroupProtectionAllowLimitedAccess) -or `
        ($SiteAndGroupProtectionAllowFullAccess -and $SiteAndGroupProtectionBlockAccess) -or `
        ($SiteAndGroupProtectionBlockAccess -and $SiteAndGroupProtectionAllowLimitedAccess))
    {
        throw '[ERROR] Only one of these values can be set to true: SiteAndGroupProtectionAllowFullAccess, SiteAndGroupProtectionAllowLimitedAccess, SiteAndGroupProtectionBlockAccess'
    }

    if ($PSBoundParameters.ContainsKey('EncryptionProtectionType') -and `
        ($EncryptionProtectionType -ne 'UserDefined' -and `
            ($PSBoundParameters.ContainsKey('EncryptionDoNotForward') -or `
                    $PSBoundParameters.ContainsKey('EncryptionEncryptOnly') -or `
                    $PSBoundParameters.ContainsKey('EncryptionPromptUser'))))
    {
        Write-Warning -Message "You have specified EncryptionDoNotForward, EncryptionEncryptOnly or EncryptionPromptUser, but EncryptionProtectionType isn't set to UserDefined."
    }

    if ('Present' -eq $Ensure -and $PSBoundParameters.ContainsKey('AutoLabelingSettings'))
    {
        Write-Verbose 'Generating required JSON string for AutoLabelingSettings'

        Write-Verbose 'Retrieving all existing Sensitive Information Types'
        $existingSITs = Get-DlpSensitiveInformationType | Select-Object -Property Name, Id, RulePackId

        # Convert the AutoLabelingSettings to the correct JSON format, ready to be inserted into the label cmdlets
        $autoLabelingSettingsHT = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $AutoLabelingSettings

        Write-Verbose 'Processing all setting groups'
        [array]$grps = foreach ($group in $autoLabelingSettingsHT.Groups)
        {
            $groupCollection = @()
            Write-Verbose 'Processing all Sensitive Information Types'
            foreach ($sit in $group.SensitiveInformationType)
            {
                $currentSIT = $existingSITs | Where-Object { $_.Name -eq $sit.Name }
                if ($null -eq $currentSIT)
                {
                    throw "[ERROR] Provided Sensitive Information Type $($sit.Name) doesn't exist."
                }

                [array]$settingsCollection = foreach ($setting in ($sit.Keys | Where-Object { $_ -ne 'id' }))
                {
                    @{
                        Key   = $setting
                        Value = $sit[$setting]
                    }
                }
                $settingsCollection += @{
                    Key   = 'rulepackage'
                    Value = $currentSIT.RulePackId
                }
                $settingsCollection += @{
                    Key   = 'groupname'
                    Value = $group.Name
                }

                if ($autoLabelingSettingsHT.ContainsKey('PolicyTip'))
                {
                    $settingsCollection += @{
                        Key   = 'policytip'
                        Value = $autoLabelingSettingsHT.PolicyTip
                    }
                }

                if ($autoLabelingSettingsHT.ContainsKey('AutoApplyType') -and $autoLabelingSettingsHT.AutoApplyType -eq 'Recommend')
                {
                    $settingsCollection += @{
                        Key   = 'autoapplytype'
                        Value = $autoLabelingSettingsHT.AutoApplyType
                    }
                }

                $groupCollection += @{
                    Key        = 'CCSI'
                    Value      = $currentSIT.Id
                    Properties = $null
                    Settings   = $settingsCollection
                }
            }

            Write-Verbose 'Processing all Trainable Classifiers'
            foreach ($trainableClassifier in $group.TrainableClassifier)
            {
                $currentTrainableClassifier = $allTrainableClassifiers | Where-Object { $_.Name -eq $trainableClassifier.name }
                if ($null -ne $currentTrainableClassifier)
                {
                    if ([String]::IsNullOrEmpty($trainableClassifier.id) -eq $false -and `
                            $trainableClassifier.id -ne $currentTrainableClassifier.Id)
                    {
                        Write-Verbose ("[WARNING] Provided ID ($($trainableClassifier.id)) does not match the known " + `
                                "ID ($($currentTrainableClassifier.id)) for trainable classifier '$($trainableClassifier.name)'.")
                    }
                    $requiredId = $currentTrainableClassifier.Id
                }
                else
                {
                    if ([String]::IsNullOrEmpty($trainableClassifier.id))
                    {
                        throw "[ERROR] Trainable classifier $($trainableClassifier.name) isn't a default classifier and no ID was provided."
                    }
                    $requiredId = $trainableClassifier.id
                }

                [array]$settingsCollection = foreach ($key in ($trainableClassifier.Keys | Where-Object { $_ -ne 'id' }))
                {
                    @{
                        Key   = $key
                        Value = $trainableClassifier[$key]
                    }
                }
                $settingsCollection += @{
                    Key   = 'groupname'
                    Value = $group.Name
                }

                if ($autoLabelingSettingsHT.ContainsKey('PolicyTip'))
                {
                    $settingsCollection += @{
                        Key   = 'policytip'
                        Value = $autoLabelingSettingsHT.PolicyTip
                    }
                }

                if ($autoLabelingSettingsHT.ContainsKey('AutoApplyType') -and $autoLabelingSettingsHT.AutoApplyType -eq 'Recommend')
                {
                    $settingsCollection += @{
                        Key   = 'autoapplytype'
                        Value = $autoLabelingSettingsHT.AutoApplyType
                    }
                }

                $groupCollection += @{
                    Key        = 'ContentMatchesModule'
                    Value      = $requiredId
                    Properties = $null
                    Settings   = $settingsCollection
                }
            }

            @{
                $group.Operator = $groupCollection
            }
        }

        $desiredAutoLabelingSettings = @{
            $autoLabelingSettingsHT.Operator = $grps
        }
        Write-Verbose 'Completed generating required JSON string for AutoLabelingSettings'
    }

    if (('Present' -eq $Ensure) -and ('Absent' -eq $label.Ensure))
    {
        Write-Verbose -Message "Label {$Name} doesn't already exist, creating it from the Set-TargetResource function."
        $CreationParams = ([Hashtable]$PSBoundParameters).Clone()

        if ($PSBoundParameters.ContainsKey('AdvancedSettings'))
        {
            $advanced = Convert-CIMToAdvancedSettings $AdvancedSettings
            $CreationParams['AdvancedSettings'] = $advanced
        }

        if ($PSBoundParameters.ContainsKey('LocaleSettings'))
        {
            $locale = Convert-CIMToLocaleSettings $LocaleSettings
            $CreationParams['LocaleSettings'] = $locale
        }

        if ($CreationParams.ContainsKey('SiteAndGroupExternalSharingControlType'))
        {
            $CreationParams.SiteExternalSharingControlType = $CreationParams.SiteAndGroupExternalSharingControlType
            $CreationParams.Remove('SiteAndGroupExternalSharingControlType')
        }

        if ($PSBoundParameters.ContainsKey('AutoLabelingSettings') -and $null -ne $desiredAutoLabelingSettings)
        {
            $CreationParams.Conditions = $desiredAutoLabelingSettings | ConvertTo-Json -Depth 20
            $CreationParams.Remove('AutoLabelingSettings')
        }

        $CreationParams.Remove('Priority') | Out-Null

        # Remove authentication parameters
        $CreationParams.Remove('Ensure') | Out-Null
        $CreationParams.Remove('Credential') | Out-Null
        $CreationParams.Remove('ApplicationId') | Out-Null
        $CreationParams.Remove('TenantId') | Out-Null
        $CreationParams.Remove('CertificatePath') | Out-Null
        $CreationParams.Remove('CertificatePassword') | Out-Null
        $CreationParams.Remove('CertificateThumbprint') | Out-Null
        $CreationParams.Remove('ManagedIdentity') | Out-Null
        $CreationParams.Remove('ApplicationSecret') | Out-Null
        $CreationParams.Remove('AccessTokens') | Out-Null

        try
        {
            Write-Verbose -Message "Creating Label {$Name}"
            $newLabel = New-Label @CreationParams -ErrorAction Stop

            ## Can't set priority until label created
            if ($PSBoundParameters.ContainsKey('Priority') -and $Priority -lt $newLabel.Priority)
            {
                Start-Sleep 5
                Write-Verbose -Message "Updating the priority for newly created label {$Name}"
                Set-Label -Identity $Name -priority $Priority -ErrorAction Stop
            }
        }
        catch
        {
            New-M365DSCLogEntry -Message 'Error retrieving data:' `
                -Exception $_ `
                -Source $($MyInvocation.MyCommand.Source) `
                -TenantId $TenantId `
                -Credential $Credential

            throw $_
        }
    }
    elseif (('Present' -eq $Ensure) -and ('Present' -eq $label.Ensure))
    {
        Write-Verbose -Message "Label {$Name} already exist, updating it from the Set-TargetResource function."
        $SetParams = $PSBoundParameters

        if ($PSBoundParameters.ContainsKey('AdvancedSettings'))
        {
            $advanced = Convert-CIMToAdvancedSettings $AdvancedSettings
            $SetParams['AdvancedSettings'] = $advanced
        }

        if ($PSBoundParameters.ContainsKey('LocaleSettings'))
        {
            $locale = Convert-CIMToLocaleSettings $LocaleSettings
            $SetParams['LocaleSettings'] = $locale
        }

        if ($SetParams.ContainsKey('SiteAndGroupExternalSharingControlType'))
        {
            $SetParams.SiteExternalSharingControlType = $SetParams.SiteAndGroupExternalSharingControlType
            $SetParams.Remove('SiteAndGroupExternalSharingControlType')
        }

        if ($PSBoundParameters.ContainsKey('AutoLabelingSettings') -and $null -ne $desiredAutoLabelingSettings)
        {
            $SetParams.Conditions = $desiredAutoLabelingSettings | ConvertTo-Json -Depth 20
            $SetParams.Remove('AutoLabelingSettings')
        }

        #Remove unused parameters for Set-Label cmdlet
        $SetParams.Remove('Name') | Out-Null

        # Remove authentication parameters
        $SetParams.Remove('Ensure') | Out-Null
        $SetParams.Remove('Credential') | Out-Null
        $SetParams.Remove('ApplicationId') | Out-Null
        $SetParams.Remove('TenantId') | Out-Null
        $SetParams.Remove('CertificatePath') | Out-Null
        $SetParams.Remove('CertificatePassword') | Out-Null
        $SetParams.Remove('CertificateThumbprint') | Out-Null
        $SetParams.Remove('ManagedIdentity') | Out-Null
        $SetParams.Remove('ApplicationSecret') | Out-Null
        $SetParams.Remove('AccessTokens') | Out-Null

        try
        {
            Set-Label @SetParams -Identity $Name -ErrorAction Stop
        }
        catch
        {
            New-M365DSCLogEntry -Message 'Error retrieving data:' `
                -Exception $_ `
                -Source $($MyInvocation.MyCommand.Source) `
                -TenantId $TenantId `
                -Credential $Credential

            throw $_
        }
    }
    elseif (('Absent' -eq $Ensure) -and ('Present' -eq $label.Ensure))
    {
        # If the label exists and it shouldn't, simply remove it;Need to force deletoion
        Write-Verbose -Message "Deleting Sensitivity label $Name."

        try
        {
            Remove-Label -Identity $Name -Confirm:$false -ErrorAction Stop
            Remove-Label -Identity $Name -Confirm:$false -forcedeletion:$true -ErrorAction Stop
        }
        catch
        {
            New-M365DSCLogEntry -Message 'Error retrieving data:' `
                -Exception $_ `
                -Source $($MyInvocation.MyCommand.Source) `
                -TenantId $TenantId `
                -Credential $Credential

            throw $_
        }
    }
}

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [Parameter()]
        [System.String]
        $Comment,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $AdvancedSettings,

        [Parameter()]
        [System.String]
        $DisplayName,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $LocaleSettings,

        [Parameter()]
        [System.String]
        $ParentId,

        [Parameter()]
        [uint32]
        $Priority,

        [Parameter()]
        [System.String]
        $Tooltip,

        [Parameter()]
        [ValidateSet('Present', 'Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [ValidateSet('Left', 'Center', 'Right')]
        [System.String]
        $ApplyContentMarkingFooterAlignment,

        [Parameter()]
        [System.Boolean]
        $ApplyContentMarkingFooterEnabled,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingFooterFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingFooterFontSize,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingFooterMargin,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingFooterText,

        [Parameter()]
        [ValidateSet('Left', 'Center', 'Right')]
        [System.String]
        $ApplyContentMarkingHeaderAlignment,

        [Parameter()]
        [System.Boolean]
        $ApplyContentMarkingHeaderEnabled,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingHeaderFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingHeaderFontSize,

        [Parameter()]
        [System.Int32]
        $ApplyContentMarkingHeaderMargin,

        [Parameter()]
        [System.String]
        $ApplyContentMarkingHeaderText,

        [Parameter()]
        [System.Boolean]
        $ApplyWaterMarkingEnabled,

        [Parameter()]
        [System.String]
        $ApplyWaterMarkingFontColor,

        [Parameter()]
        [System.Int32]
        $ApplyWaterMarkingFontSize,

        [Parameter()]
        [ValidateSet('Horizontal', 'Diagonal')]
        [System.String]
        $ApplyWaterMarkingLayout,

        [Parameter()]
        [System.String]
        $ApplyWaterMarkingText,

        [Parameter()]
        [ValidateSet('File, Email', 'Site, UnifiedGroup', 'PurviewAssets', 'Teamwork', 'SchematizedData')]
        [System.String[]]
        $ContentType,

        [Parameter()]
        [System.String]
        $EncryptionContentExpiredOnDateInDaysOrNever,

        [Parameter()]
        [System.Boolean]
        $EncryptionDoNotForward,

        [Parameter()]
        [System.Boolean]
        $EncryptionEncryptOnly,

        [Parameter()]
        [System.Boolean]
        $EncryptionEnabled,

        [Parameter()]
        [System.Int32]
        $EncryptionOfflineAccessDays,

        [Parameter()]
        [System.Boolean]
        $EncryptionPromptUser,

        [Parameter()]
        [System.String]
        $EncryptionProtectionType,

        [Parameter()]
        [System.String]
        $EncryptionRightsDefinitions,

        [Parameter()]
        [System.String]
        $EncryptionRightsUrl,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowAccessToGuestUsers,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowEmailFromGuestUsers,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowFullAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionAllowLimitedAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionBlockAccess,

        [Parameter()]
        [System.Boolean]
        $SiteAndGroupProtectionEnabled,

        [Parameter()]
        [ValidateSet('Public', 'Private', 'Unspecified')]
        [System.String]
        $SiteAndGroupProtectionPrivacy,

        [Parameter()]
        [ValidateSet('ExternalUserAndGuestSharing', 'ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', 'Disabled')]
        [System.String]
        $SiteAndGroupExternalSharingControlType,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance]
        $AutoLabelingSettings,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [System.String]
        $CertificatePath,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $CertificatePassword,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )
    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    Write-Verbose -Message "Testing configuration of Sensitivity label for $Name"

    $CurrentValues = Get-TargetResource @PSBoundParameters
    Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)"
    Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)"

    $ValuesToCheck = $PSBoundParameters
    $ValuesToCheck.Remove('AdvancedSettings') | Out-Null
    $ValuesToCheck.Remove('LocaleSettings') | Out-Null
    $ValuesToCheck.Remove('AutoLabelingSettings') | Out-Null

    if ($null -ne $AdvancedSettings -and $null -ne $CurrentValues.AdvancedSettings)
    {
        Write-Verbose -Message 'Testing AdvancedSettings'
        $TestAdvancedSettings = Test-AdvancedSettings -DesiredProperty $AdvancedSettings -CurrentProperty $CurrentValues.AdvancedSettings
        if ($false -eq $TestAdvancedSettings)
        {
            return $false
        }
    }

    if ($null -ne $LocaleSettings -and $null -ne $CurrentValues.LocaleSettings)
    {
        Write-Verbose -Message 'Testing LocaleSettings'
        $localeSettingsSame = Test-LocaleSettings -DesiredProperty $LocaleSettings -CurrentProperty $CurrentValues.LocaleSettings
        if ($false -eq $localeSettingsSame)
        {
            return $false
        }
    }

    if ($null -ne $AutoLabelingSettings -and $null -ne $CurrentValues.AutoLabelingSettings)
    {
        Write-Verbose -Message 'Testing AutoLabelingSettings'

        # Convert the AutoLabelingSettings to the correct JSON format, ready to be inserted into the label cmdlets
        $autoLabelingSettingsHT = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $AutoLabelingSettings

        $autoLabelSettingsSame = Test-AutoLabelingSettings -CurrentProperty $CurrentValues.AutoLabelingSettings -DesiredProperty $autoLabelingSettingsHT
        if ($false -eq $autoLabelSettingsSame)
        {
            return $false
        }
    }

    $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues `
        -Source $($MyInvocation.MyCommand.Source) `
        -DesiredValues $PSBoundParameters `
        -ValuesToCheck $ValuesToCheck.Keys

    Write-Verbose -Message "Test-TargetResource returned $TestResult"
    return $TestResult
}

function Export-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [System.String]
        $CertificatePath,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $CertificatePassword,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )
    $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' `
        -InboundParameters $PSBoundParameters `
        -SkipModuleReload $true

    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    try
    {
        [array]$labels = Get-Label -ErrorAction Stop

        $dscContent = ''
        $i = 1
        if ($labels.Length -eq 0)
        {
            Write-Host $Global:M365DSCEmojiGreenCheckMark
        }
        else
        {
            Write-Host "`r`n" -NoNewline
        }
        foreach ($label in $labels)
        {
            if ($null -ne $Global:M365DSCExportResourceInstancesCount)
            {
                $Global:M365DSCExportResourceInstancesCount++
            }

            Write-Host " |---[$i/$($labels.Count)] $($label.Name)" -NoNewline

            $Results = Get-TargetResource @PSBoundParameters -Name $label.Name

            if ($null -ne $Results.AdvancedSettings)
            {
                $Results.AdvancedSettings = ConvertTo-AdvancedSettingsString -AdvancedSettings $Results.AdvancedSettings
            }

            if ($null -ne $Results.LocaleSettings)
            {
                $Results.LocaleSettings = ConvertTo-LocaleSettingsString -LocaleSettings $Results.LocaleSettings
            }
            if ($null -ne $Results.AutoLabelingSettings)
            {
                $Results.AutoLabelingSettings = ConvertTo-AutoLabelingSettingsString -AutoLabelingSettings $Results.AutoLabelingSettings
            }
            $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode `
                -Results $Results
            $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName `
                -ConnectionMode $ConnectionMode `
                -ModulePath $PSScriptRoot `
                -Results $Results `
                -Credential $Credential
            if ($null -ne $Results.AdvancedSettings)
            {
                $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'AdvancedSettings'
            }
            if ($null -ne $Results.LocaleSettings)
            {
                $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LocaleSettings'
            }
            if ($null -ne $Results.AutoLabelingSettings)
            {
                $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'AutoLabelingSettings'
            }

            Write-Host $Global:M365DSCEmojiGreenCheckMark
            $dscContent += $currentDSCBlock
            Save-M365DSCPartialExport -Content $currentDSCBlock `
                -FileName $Global:PartialExportFileName
            $i++
        }
    }
    catch
    {
        Write-Host $Global:M365DSCEmojiRedX

        New-M365DSCLogEntry -Message 'Error during Export:' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential

        return ''
    }
    return $dscContent
}

function Convert-JSONToLocaleSettings
{
    [CmdletBinding()]
    [OutputType([Microsoft.Management.Infrastructure.CimInstance[]])]
    param
    (
        [parameter(Mandatory = $true)]
        $JSONLocalSettings
    )

    $localeSettings = $JSONLocalSettings | ConvertFrom-Json

    $entries = @()
    $settings = @()
    foreach ($localeSetting in $localeSettings)
    {
        $result = @{
            localeKey = $localeSetting.LocaleKey
        }
        foreach ($setting in $localeSetting.Settings)
        {
            $entry = @{
                Key   = $setting.Key
                Value = $setting.Value -replace "`r"
            }
            $settings += $entry
        }
        $result.Add('LabelSettings', $settings)
        $settings = @()
        $entries += $result
        $result = @{ }
    }
    return $entries
}

function Convert-StringToAdvancedSettings
{
    [CmdletBinding()]
    [OutputType([Microsoft.Management.Infrastructure.CimInstance[]])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String[]]
        $AdvancedSettings
    )

    $settings = @()
    foreach ($setting in $AdvancedSettings)
    {
        $settingString = $setting.Replace('[', '').Replace(']', '')
        $settingKey = $settingString.Split(',')[0]

        if ($settingKey -notin @('displayname', 'contenttype', 'tooltip', 'parentid'))
        {
            $startPos = $settingString.IndexOf(',', 0) + 1
            $valueString = $settingString.Substring($startPos, $settingString.Length - $startPos).Trim()
            $values = $valueString.Split(',')

            $entry = @{
                Key   = $settingKey
                Value = $values.Trim()
            }
            $settings += $entry
        }
    }
    return $settings
}

function Convert-CIMToAdvancedSettings
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $AdvancedSettings
    )

    $entry = @{ }
    foreach ($obj in $AdvancedSettings)
    {
        $settingsValues = ''
        foreach ($objVal in $obj.Value)
        {
            $settingsValues += $objVal
            $settingsValues += ','
        }
        $entry[$obj.Key] = $settingsValues.Substring(0, ($settingsValues.Length - 1))
    }

    return $entry
}

function Convert-EncryptionRightDefinition
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $RightsDefinition
    )

    $EncryptionRights = $RightsDefinition | ConvertFrom-Json
    foreach ($right in $EncryptionRights)
    {
        $StringContent += "$($right.Identity):$($right.Rights);"
    }
    if ($StringContent.EndsWith(';'))
    {
        $StringContent = $StringContent.Substring(0, ($StringContent.Length - 1))
    }
    return $StringContent

}

function Convert-CIMToLocaleSettings
{
    [CmdletBinding()]
    [OutputType([System.Collections.ArrayList])]
    param
    (
        [parameter(Mandatory = $true)]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $localeSettings
    )

    $entry = [System.Collections.ArrayList]@()
    foreach ($localset in $localeSettings)
    {
        $localeEntries = [ordered]@{
            localeKey = $localset.LocaleKey
        }
        $settings = @()
        foreach ($setting in $localset.LabelSettings)
        {
            $settingEntry = @{
                Key   = $setting.Key
                Value = $setting.Value
            }
            $settings += $settingEntry
        }
        $localeEntries.Add('Settings', $settings)
        [void]$entry.Add(($localeEntries | ConvertTo-Json))
        $localeEntries = @{ }
        $settings = @( )
    }

    return $entry
}

function Test-AdvancedSettings
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter (Mandatory = $true)]
        $DesiredProperty,

        [Parameter (Mandatory = $true)]
        $CurrentProperty
    )

    $driftedSetting = @()
    $foundSettings = $true
    foreach ($desiredSetting in $DesiredProperty)
    {
        $foundKey = $CurrentProperty | Where-Object { $_.Key -eq $desiredSetting.Key }
        if ($null -ne $foundKey)
        {
            if ($desiredSetting.Value -is [Array])
            {
                if ($foundKey.Value -is [Array])
                {
                    $diff = Compare-Object -ReferenceObject $foundKey.Value -DifferenceObject $desiredSetting.Value
                    if ($diff.Count -ne 0)
                    {
                        $foundSettings = $false
                        $driftedSetting += $desiredSetting.Key
                    }
                }
                else
                {
                    if ($desiredSetting.Value.Count -ne 1 -or `
                            $foundKey.Value.ToString() -ne $desiredSetting.Value[0].ToString())
                    {
                        $foundSettings = $false
                        $driftedSetting += $desiredSetting.Key
                    }
                }
            }
            else
            {
                if ($foundKey.Value -is [Array])
                {
                    if ($foundKey.Value.Count -ne 1 -or `
                            $foundKey.Value[0].ToString() -ne $desiredSetting.Value.ToString())
                    {
                        $foundSettings = $false
                        $driftedSetting += $desiredSetting.Key
                    }
                }
                else
                {
                    if ($foundKey.Value.ToString() -ne $desiredSetting.Value.ToString())
                    {
                        $foundSettings = $false
                        $driftedSetting += $desiredSetting.Key
                    }
                }
            }
        }
        else
        {
            $foundSettings = $false
            $driftedSetting += $desiredSetting.Key
        }
    }

    if ($foundSettings -eq $false)
    {
        New-M365DSCLogEntry -Message "AdvancedSettings for label $Name do not match: $($driftedSetting -join ', ')" `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }

    Write-Verbose -Message "Test AdvancedSettings returns $foundSettings"
    return $foundSettings
}

function Test-LocaleSettings
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter (Mandatory = $true)]
        $DesiredProperty,

        [Parameter (Mandatory = $true)]
        $CurrentProperty
    )

    $driftedSetting = @()
    $foundSettings = $true
    foreach ($desiredSetting in $DesiredProperty)
    {
        $foundKey = $CurrentProperty | Where-Object { $_.LocaleKey -eq $desiredSetting.localeKey }
        foreach ($setting in $desiredSetting.LabelSettings)
        {
            if ($null -ne $foundKey)
            {
                if ($setting.Value -is [Array])
                {
                    if ($setting.Value.Count -eq 1)
                    {
                        $myLabel = $foundKey.LabelSettings | Where-Object { $_.Key -eq $setting.Key -and $_.Value -eq $setting.Value[0] }
                    }
                    else
                    {
                        $foundSettings = $false
                        $driftedSetting += "$($desiredSetting.localeKey) ($($setting.Key))"
                    }
                }
                else
                {
                    $myLabel = $foundKey.LabelSettings | Where-Object { $_.Key -eq $setting.Key -and $_.Value -eq $setting.Value }
                }

                if ($null -eq $myLabel)
                {
                    $foundSettings = $false
                    $driftedSetting += "$($desiredSetting.localeKey) ($($setting.Key))"
                }
            }
            else
            {
                $foundSettings = $false
                $driftedSetting += "$($desiredSetting.localeKey) ($($setting.Key))"
            }
        }
    }

    if ($foundSettings -eq $false)
    {
        New-M365DSCLogEntry -Message "LocaleSettings for label $Name do not match: $($driftedSetting -join ', ')" `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }

    Write-Verbose -Message "Test LocaleSettings returns $foundSettings"

    return $foundSettings
}

function Test-AutoLabelingSettings
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter (Mandatory = $true)]
        [System.Object]
        $DesiredProperty,

        [Parameter (Mandatory = $true)]
        [System.Object]
        $CurrentProperty
    )

    $foundSettings = $true
    $driftedSetting = New-Object System.Collections.ArrayList

    if ($DesiredProperty.Operator -ne $CurrentProperty.Operator)
    {
        $null = $driftedSetting.Add("Parameter 'Operator' does not match. Current: '$($CurrentProperty.Operator)'. Desired: '$($DesiredProperty.Operator)'.")
        $foundSettings = $false
    }

    if ($DesiredProperty.AutoApplyType -ne $CurrentProperty.AutoApplyType)
    {
        $null = $driftedSetting.Add("Parameter 'AutoApplyType' does not match. Current: '$($CurrentProperty.AutoApplyType)'. Desired: '$($DesiredProperty.AutoApplyType)'.")
        $foundSettings = $false
    }

    if ($DesiredProperty.ContainsKey('PolicyTip') -and $DesiredProperty.PolicyTip -ne $CurrentProperty.PolicyTip)
    {
        $null = $driftedSetting.Add("Parameter 'PolicyTip' does not match. Current: '$($CurrentProperty.PolicyTip)'. Desired: '$($DesiredProperty.PolicyTip)'.")
        $foundSettings = $false
    }

    foreach ($group in $DesiredProperty.Groups)
    {
        $currentGroup = $CurrentProperty.Groups | Where-Object { $_.Name -eq $group.Name }
        if ($null -eq $currentGroup)
        {
            $null = $driftedSetting.Add("Group '$($group.Name)' not found in the current settings.")
            $foundSettings = $false
            continue
        }

        if ($group.Operator -ne $currentGroup.Operator)
        {
            $null = $driftedSetting.Add("Parameter 'Groups\$($group.Name)\Operator' does not match. Current: '$($currentGroup.Operator)'. Desired: '$($group.Operator)'.")
            $foundSettings = $false
        }

        foreach ($sensitiveinfotype in $group.SensitiveInformationType)
        {
            $currentSensitiveInfoType = $currentGroup.SensitiveInformationType | Where-Object { $_.name -eq $sensitiveinfotype.name }
            if ($null -eq $currentSensitiveInfoType)
            {
                $null = $driftedSetting.Add("Sensitive Information Type '$($sensitiveinfotype.name)' not found in the current settings for group '$($group.Name)'.")
                $foundSettings = $false
                continue
            }

            if ($sensitiveinfotype.ContainsKey('confidencelevel') -and $sensitiveinfotype.confidencelevel -ne $currentSensitiveInfoType.confidencelevel)
            {
                $null = $driftedSetting.Add("Parameter 'confidencelevel' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.confidencelevel)'. Desired: '$($sensitiveinfotype.confidencelevel)'.")
                $foundSettings = $false
            }


            if ($sensitiveinfotype.ContainsKey('classifiertype') -and $sensitiveinfotype.classifiertype -ne $currentSensitiveInfoType.classifiertype)
            {
                $null = $driftedSetting.Add("Parameter 'classifiertype' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.classifiertype)'. Desired: '$($sensitiveinfotype.classifiertype)'.")
                $foundSettings = $false
            }

            if ($sensitiveinfotype.ContainsKey('mincount') -and $sensitiveinfotype.mincount -ne $currentSensitiveInfoType.mincount)
            {
                $null = $driftedSetting.Add("Parameter 'mincount' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.mincount)'. Desired: '$($sensitiveinfotype.mincount)'.")
                $foundSettings = $false
            }

            if ($sensitiveinfotype.ContainsKey('maxcount') -and $sensitiveinfotype.maxcount -ne $currentSensitiveInfoType.maxcount)
            {
                $null = $driftedSetting.Add("Parameter 'maxcount' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.maxcount)'. Desired: '$($sensitiveinfotype.maxcount)'.")
                $foundSettings = $false
            }
        }
        foreach ($trainableClassifier in $group.TrainableClassifier)
        {
            $currentTrainableClassifier = $currentGroup.trainableClassifier | Where-Object { $_.name -eq $trainableClassifier.name }
            if ($null -eq $currentTrainableClassifier)
            {
                $null = $driftedSetting.Add("Trainable Classifier '$($trainableClassifier.name)' not found in the current settings for group '$($group.Name)'.")
                $foundSettings = $false
                continue
            }
        }
    }

    foreach ($group in $CurrentProperty.Groups)
    {
        $desiredGroup = $DesiredProperty.Groups | Where-Object { $_.Name -eq $group.Name }
        if ($null -eq $desiredGroup)
        {
            $null = $driftedSetting.Add("Group '$($group.Name)' not found in the desired settings.")
            $foundSettings = $false
            continue
        }

        foreach ($sensitiveinfotype in $group.SensitiveInformationType)
        {
            $desiredSensitiveInfoType = $desiredGroup.SensitiveInformationType | Where-Object { $_.name -eq $sensitiveinfotype.name }
            if ($null -eq $desiredSensitiveInfoType)
            {
                $null = $driftedSetting.Add("Sensitive Information Type '$($sensitiveinfotype.name)' not found in the desired settings for group '$($group.Name)'.")
                $foundSettings = $false
                continue
            }
        }
        foreach ($trainableClassifier in $group.TrainableClassifier)
        {
            $desiredTrainableClassifier = $desiredGroup.trainableClassifier | Where-Object { $_.name -eq $trainableClassifier.name }
            if ($null -eq $desiredTrainableClassifier)
            {
                $null = $driftedSetting.Add("Trainable Classifier '$($trainableClassifier.name)' not found in the desired settings for group '$($group.Name)'.")
                $foundSettings = $false
                continue
            }
        }
    }

    if ($foundSettings -eq $false)
    {
        New-M365DSCLogEntry -Message "AutoLabelingSettings for label $Name do not match: `r`n- $($driftedSetting -join '`r`n- ')" `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }

    Write-Verbose -Message "Test AutoLabelingSettings returns $foundSettings"

    return $foundSettings
}

function ConvertTo-AdvancedSettingsString
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter(Mandatory = $true)]
        $AdvancedSettings
    )

    $StringContent = "@(`r`n"
    foreach ($advancedSetting in $AdvancedSettings)
    {
        $StringContent += " MSFT_SCLabelSetting`r`n"
        $StringContent += " {`r`n"
        $StringContent += " Key = '$($advancedSetting.Key.Replace("'", "''"))'`r`n"
        $StringContent += " Value = '$($advancedSetting.Value.Replace("'", "''"))'`r`n"
        $StringContent += " }`r`n"
    }
    $StringContent += ' )'
    return $StringContent
}

function ConvertTo-LocaleSettingsString
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter(Mandatory = $true)]
        $LocaleSettings
    )

    $StringContent = "@(`r`n"
    foreach ($LocaleSetting in $LocaleSettings)
    {
        $StringContent += " MSFT_SCLabelLocaleSettings`r`n"
        $StringContent += " {`r`n"
        $StringContent += " LocaleKey = '$($LocaleSetting.LocaleKey.Replace("'", "''"))'`r`n"
        $StringContent += " LabelSettings = @(`r`n"
        foreach ($Setting in $LocaleSetting.LabelSettings)
        {
            $StringContent += " MSFT_SCLabelSetting`r`n"
            $StringContent += " {`r`n"
            $StringContent += " Key = '$($Setting.Key.Replace("'", "''"))'`r`n"
            $StringContent += " Value = '$($Setting.Value.Replace("'", "''"))'`r`n"
            $StringContent += " }`r`n"
        }
        $StringContent += " )`r`n"
        $StringContent += " }`r`n"
    }
    $StringContent += ' )'
    return $StringContent
}

function ConvertTo-AutoLabelingSettingsString
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter(Mandatory = $true)]
        $AutoLabelingSettings
    )

    $StringContent = ''
    foreach ($autoLabelingSetting in $AutoLabelingSettings)
    {
        $StringContent += " MSFT_SCSLAutoLabelingSettings`r`n"
        $StringContent += " {`r`n"
        $StringContent += " Operator = '$($autoLabelingSetting.Operator)'`r`n"
        if ($autoLabelingSetting.ContainsKey('PolicyTip'))
        {
            $StringContent += " PolicyTip = '$($autoLabelingSetting.PolicyTip.Replace("'", "''"))'`r`n"
        }
        $StringContent += " AutoApplyType = '$($autoLabelingSetting.AutoApplyType)'`r`n"
        $StringContent += " Groups = @(`r`n"
        foreach ($Group in $autoLabelingSetting.Groups)
        {
            $StringContent += " MSFT_SCSLSensitiveInformationGroup`r`n"
            $StringContent += " {`r`n"
            $StringContent += " Name = '$($Group.Name.Replace("'", "''"))'`r`n"
            $StringContent += " Operator = '$($Group.Operator)'`r`n"
            if ($Group.ContainsKey('SensitiveInformationType'))
            {
                $StringContent += " SensitiveInformationType = @(`r`n"
                foreach ($sensitiveInformationType in $Group.SensitiveInformationType)
                {
                    $StringContent += " MSFT_SCSLSensitiveInformationType`r`n"
                    $StringContent += " {`r`n"
                    $StringContent += " name = '$($sensitiveInformationType.name.Replace("'", "''"))'`r`n"
                    if ($sensitiveInformationType.ContainsKey('confidencelevel'))
                    {
                        $StringContent += " confidencelevel = '$($sensitiveInformationType.confidencelevel)'`r`n"
                    }
                    if ($sensitiveInformationType.ContainsKey('classifiertype'))
                    {
                        $StringContent += " classifiertype = '$($sensitiveInformationType.classifiertype)'`r`n"
                    }
                    if ($sensitiveInformationType.ContainsKey('mincount'))
                    {
                        $StringContent += " mincount = '$($sensitiveInformationType.mincount)'`r`n"
                    }
                    if ($sensitiveInformationType.ContainsKey('maxcount'))
                    {
                        $StringContent += " maxcount = '$($sensitiveInformationType.maxcount)'`r`n"
                    }
                    $StringContent += " }`r`n"
                }
                $StringContent += " )`r`n"
            }
            if ($Group.ContainsKey('TrainableClassifier'))
            {
                $StringContent += " TrainableClassifier = @(`r`n"
                foreach ($trainableClassifier in $Group.TrainableClassifier)
                {
                    $StringContent += " MSFT_SCSLTrainableClassifiers`r`n"
                    $StringContent += " {`r`n"
                    $StringContent += " name = '$($trainableClassifier.name.Replace("'", "''"))'`r`n"
                    if ($trainableClassifier.ContainsKey('id'))
                    {
                        $StringContent += " id = '$($trainableClassifier.id)'`r`n"
                    }
                    $StringContent += " }`r`n"
                }
                $StringContent += " )`r`n"
            }
            $StringContent += " }`r`n"
        }
        $StringContent += " )`r`n"
        $StringContent += " }`r`n"
    }
    return $StringContent
}

Export-ModuleMember -Function *-TargetResource