/// <summary>
        /// Updates the extended properties.
        /// </summary>
        /// <param name="targetUser">The target user.</param>
        /// <param name="sourceUser">The source user.</param>
        /// <returns><see langword="true"/> if the user was updated, else <see langword="false"/>.</returns>
        public static bool UpdateExtendedProperties(this User targetUser, UpdateUser sourceUser)
        {
            var updated = false;

            var addExtendedProperties = sourceUser.ExtendedPropertyUpdates.Where(x => x.OperationType == UpdateOperationType.Upsert);
            foreach (var addExtendedProperty in addExtendedProperties)
            {
                var newProperty = addExtendedProperty.UpdateObject;
                if (targetUser.ExtendedProperties.ContainsKey(newProperty.Key) && targetUser.ExtendedProperties[newProperty.Key] == newProperty.Value)
                {
                    continue;
                }

                targetUser.ExtendedProperties[newProperty.Key] = newProperty.Value;
                updated = true;
            }

            var removeExtendedProperties = sourceUser.ExtendedPropertyUpdates.Where(x => x.OperationType == UpdateOperationType.Remove);
            foreach (var removeExtendedProperty in removeExtendedProperties)
            {
                var newProperty = removeExtendedProperty.UpdateObject;
                if (!targetUser.ExtendedProperties.ContainsKey(newProperty.Key))
                {
                    continue;
                }

                targetUser.ExtendedProperties.Remove(newProperty.Key);
                updated = true;
            }

            return updated;
        }
        /// <summary>
        /// Maps properties from <paramref name="targetUser"/> to <paramref name="sourceUser"/>
        /// </summary>
        /// <param name="targetUser">The user to have properties mapped from.</param>
        /// <param name="sourceUser">The user to have properties mapped to.</param>
        /// <returns><see langword="true"/> if the user was updated, else <see langword="false"/>.</returns>
        public static bool MapUserData(this User targetUser, UpdateUser sourceUser)
        {
            var updated = false;
            if (!string.IsNullOrWhiteSpace(sourceUser.DisplayName) && targetUser.DisplayName != sourceUser.DisplayName)
            {
                targetUser.DisplayName = sourceUser.DisplayName;
                updated = true;
            }

            if (!string.IsNullOrWhiteSpace(sourceUser.EmailAddress) && targetUser.EmailAddress != sourceUser.EmailAddress)
            {
                targetUser.EmailAddress = sourceUser.EmailAddress;
                updated = true;
            }

            if (!string.IsNullOrWhiteSpace(sourceUser.Username) && targetUser.Username != sourceUser.Username)
            {
                targetUser.Username = sourceUser.Username;
                updated = true;
            }

            return updated;
        }
        /// <summary>
        /// Adds and removes roles from the user <paramref name="sourceUser"/>, to match with <paramref name="targetUser"/>
        /// </summary>
        /// <param name="targetUser">The user that should be matched.</param>
        /// <param name="sourceUser">The user to have roles added and removed.</param>
        /// <param name="roles">The role list.</param>
        /// <returns><see langword="true"/> if the user was updated, else <see langword="false"/>.</returns>
        public static bool UpdateRoles(this User targetUser, UpdateUser sourceUser, RoleList roles)
        {
            var updated = false;

            var addRoles = sourceUser.RoleUpdates.Where(x => x.OperationType == UpdateOperationType.Upsert);
            foreach (var addRole in addRoles)
            {
                var role = roles.FirstOrDefault(r => r.Id == addRole.UpdateObject);
                if (role == null || targetUser.Roles.ContainsKey(role.Id))
                {
                    continue;
                }

                targetUser.Roles[role.Id] = role.RoleName;
                updated = true;
            }

            var removeRoles = sourceUser.RoleUpdates.Where(x => x.OperationType == UpdateOperationType.Remove);
            foreach (var removeRole in removeRoles)
            {
                if (!targetUser.Roles.ContainsKey(removeRole.UpdateObject))
                {
                    continue;
                }

                targetUser.Roles.Remove(removeRole.UpdateObject);
                updated = true;
            }

            return updated;
        }