//UI magic to group the path pairs from profile variables
        internal static List<ProfileGroupType> CreateGroupTypes(AddressableAssetProfileSettings.BuildProfile buildProfile)
        {
            AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings;
            Dictionary<string, ProfileGroupType> groups = new Dictionary<string, ProfileGroupType>();
            foreach (var profileEntry in settings.profileSettings.profileEntryNames)
            {
                string[] parts = profileEntry.ProfileName.Split(k_PrefixSeparator);
                if (parts.Length > 1)
                {
                    string prefix = String.Join(k_PrefixSeparator.ToString(), parts, 0, parts.Length - 1);
                    string suffix = parts[parts.Length - 1];
                    string profileEntryValue = buildProfile.GetValueById(profileEntry.Id);
                    ProfileGroupType group;
                    groups.TryGetValue(prefix, out group);
                    if (group == null)
                    {
                        group = new ProfileGroupType(prefix);
                    }
                    GroupTypeVariable variable = new GroupTypeVariable(suffix, profileEntryValue);
                    group.AddVariable(variable);
                    groups[prefix] = group;
                }
            }

            List<ProfileGroupType> groupList = new List<ProfileGroupType>();
            groupList.AddRange(groups.Values.Where(group => group.IsValidGroupType()));
            return groupList;
        }
        static ProfileGroupType CreateBuiltInGroupType()
        {
            ProfileGroupType defaultBuiltIn = new ProfileGroupType(AddressableAssetSettings.LocalGroupTypePrefix);

            defaultBuiltIn.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kBuildPath, AddressableAssetSettings.kLocalBuildPathValue));
            defaultBuiltIn.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kLoadPath, AddressableAssetSettings.kLocalLoadPathValue));
            return(defaultBuiltIn);
        }
        static ProfileGroupType CreateEditorHostedGroupType()
        {
            ProfileGroupType defaultRemote = new ProfileGroupType(AddressableAssetSettings.EditorHostedGroupTypePrefix);

            defaultRemote.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kBuildPath, AddressableAssetSettings.kRemoteBuildPathValue));
            defaultRemote.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kLoadPath, AddressableAssetSettings.RemoteLoadPathValue));
            return(defaultRemote);
        }
        /// <summary>
        /// Updates the CCD buckets and badges with the data source settings
        /// </summary>
        /// <param name="projectId">Project Id connected to Unity Services</param>
        /// <param name="showInfoLog">Whether or not to show debug logs or not</param>
        /// <returns>List of ProfileGroupType</returns>
        public static async Task <List <ProfileGroupType> > UpdateCCDDataSourcesAsync(string projectId, bool showInfoLog)
        {
            if (showInfoLog)
            {
                Addressables.Log("Syncing CCD Buckets and Badges.");
            }
            var settings          = GetSettings();
            var profileGroupTypes = new List <ProfileGroupType>();

            profileGroupTypes.AddRange(CreateDefaultGroupTypes());

            await CCDManagementAPIService.SetConfigurationAuthHeader(CloudProjectSettings.accessToken);

            var bucketDictionary = await GetAllBucketsAsync(projectId);

            foreach (var kvp in bucketDictionary)
            {
                var bucket = kvp.Value;
                var badges = await GetAllBadgesAsync(projectId, bucket.Id.ToString());

                if (badges.Count == 0)
                {
                    badges.Add(new CcdBadge(name: "latest"));
                }
                foreach (var badge in badges)
                {
                    var groupType = new ProfileGroupType($"CCD{ProfileGroupType.k_PrefixSeparator}{projectId}{ProfileGroupType.k_PrefixSeparator}{bucket.Id}{ProfileGroupType.k_PrefixSeparator}{badge.Name}");
                    groupType.AddVariable(new ProfileGroupType.GroupTypeVariable($"{nameof(CcdBucket)}{nameof(CcdBucket.Name)}", bucket.Name));
                    groupType.AddVariable(new ProfileGroupType.GroupTypeVariable($"{nameof(CcdBucket)}{nameof(CcdBucket.Id)}", bucket.Id.ToString()));
                    groupType.AddVariable(new ProfileGroupType.GroupTypeVariable($"{nameof(CcdBadge)}{nameof(CcdBadge.Name)}", badge.Name));
                    groupType.AddVariable(new ProfileGroupType.GroupTypeVariable(nameof(CcdBucket.Attributes.PromoteOnly), bucket.Attributes.PromoteOnly.ToString()));

                    string buildPath = $"{AddressableAssetSettings.kCCDBuildDataPath}/{bucket.Id}/{badge.Name}";
                    groupType.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kBuildPath, buildPath));

                    string loadPath = $"https://{projectId}.client-api.unity3dusercontent.com/client_api/v1/buckets/{bucket.Id}/release_by_badge/{badge.Name}/entry_by_path/content/?path=";
                    groupType.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kLoadPath, loadPath));

                    profileGroupTypes.Add(groupType);
                }
            }
            settings.profileGroupTypes = profileGroupTypes;
            if (showInfoLog)
            {
                Addressables.Log("Successfully synced CCD Buckets and Badges.");
            }
            EditorUtility.SetDirty(settings);
            AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings);
            return(settings.profileGroupTypes);
        }
        /// <summary>
        /// Given a valid profileGroupType, searches the settings and returns, if exists, the profile group type
        /// </summary>
        /// <param name="groupType"></param>
        /// <returns>ProfileGroupType if found, null otherwise</returns>
        public ProfileGroupType FindGroupType(ProfileGroupType groupType)
        {
            ProfileGroupType result = null;

            if (!groupType.IsValidGroupType())
            {
                throw new ArgumentException("Group Type is not valid. Group Type must include a build path and load path variables");
            }

            foreach (ProfileGroupType settingsGroupType in profileGroupTypes)
            {
                var buildPath      = groupType.GetVariableBySuffix(AddressableAssetSettings.kBuildPath);
                var foundBuildPath = settingsGroupType.ContainsVariable(buildPath);
                var loadPath       = groupType.GetVariableBySuffix(AddressableAssetSettings.kLoadPath);
                var foundLoadPath  = settingsGroupType.ContainsVariable(loadPath);
                if (foundBuildPath && foundLoadPath)
                {
                    result = settingsGroupType;
                    break;
                }
            }
            return(result);
        }