/// <summary>
        /// Returns a version group entry for the given version group.
        /// </summary>
        protected override async Task <VersionGroupEntry> ConvertToEntry(VersionGroup versionGroup)
        {
            var displayNames = await GetDisplayNames(versionGroup);

            var generation = await GenerationsService.GetByVersionGroup(versionGroup);

            var versions = await VersionsService.UpsertMany(versionGroup.Versions);

            var pokedexes = await PokedexesService.UpsertMany(versionGroup.Pokedexes);

            return(new VersionGroupEntry
            {
                Key = versionGroup.Id,
                Name = versionGroup.Name,
                Order = versionGroup.Order,
                DisplayNames = displayNames.ToList(),
                Generation = new Generation
                {
                    Id = generation.GenerationId,
                    Name = generation.Name
                },
                Versions = versions.ToList(),
                Pokedexes = pokedexes.Select(p => new Pokedex
                {
                    Id = p.PokedexId,
                    Name = p.Name
                }).ToList()
            });
        }
        /// <summary>
        /// Returns the Pokemon's encounters in all version groups.
        /// </summary>
        private async Task <List <WithId <EncounterEntry[]> > > GetEncounters(Pokemon pokemon)
        {
            var encounterEntriesList = new List <WithId <EncounterEntry[]> >();

            // enumerate version groups spanned by this Pokemon's encounters
            // TODO: create encounters cache service
            var encounters = await PokeApi.GetEncounters(pokemon);

            var versions = await VersionService.UpsertMany(encounters.GetDistinctVersions());

            var versionGroups = await VersionGroupsService.UpsertManyByVersionIds(versions.Select(v => v.VersionId));

            foreach (var vg in versionGroups)
            {
                var relevantEncounters = encounters.Where(e => IsInVersionGroup(e, vg));

                // create entries for relevant encounters
                var encounterEntries = new List <EncounterEntry>();
                foreach (var encounter in relevantEncounters)
                {
                    var locationArea = await LocationAreasService.Upsert(encounter.LocationArea);

                    var displayNames = await GetDisplayNames(encounter);

                    // filter to relevant version details
                    var relevantVersionDetails = encounter.VersionDetails.Where(vd =>
                    {
                        var versionName = vd.Version.Name;
                        return(vg.Versions.Select(v => v.Name).Contains(versionName));
                    });

                    var chances = await GetChances(relevantVersionDetails);

                    var encounterDetails = await GetEncounterDetails(relevantVersionDetails);

                    var encounterEntry = new EncounterEntry
                    {
                        LocationAreaId = locationArea.LocationAreaId,
                        DisplayNames   = displayNames.ToList(),
                        Details        = encounterDetails.ToList()
                    };

                    encounterEntries.Add(encounterEntry);
                }

                // add encounter entries to list indexed by version group ID
                var entryList = new WithId <EncounterEntry[]>(vg.VersionGroupId, encounterEntries.ToArray());
                encounterEntriesList.Add(entryList);
            }

            return(encounterEntriesList);
        }