public AnidbEpisode ToAnidb(TvdbEpisode tvdb)
        {
            List<AnimelistAnime> animeList;
            if (!_tvdbMappings.TryGetValue(tvdb.Series, out animeList))
                return null;
            
            // look for exact mapping in mapping list
            foreach (var anime in animeList.Where(x => x.Mappinglist != null))
            {
                var mappings = anime.Mappinglist.Where(x => x.TvdbSeason == tvdb.Season);
                foreach (var mapping in mappings)
                {
                    var episode = FindTvdbEpisodeMapping(tvdb, mapping);

                    if (episode != null)
                    {
                        return new AnidbEpisode
                        {
                            Series = anime.AnidbId,
                            Season = mapping.AnidbSeason,
                            Index = episode.Value
                        };
                    }
                }
            }

            var seasonMatch = animeList
                .Select(x => new {Season = Parse(x.DefaultTvdbSeason), Match = x})
                .Where(x => x.Season == tvdb.Season)
                .Select(x => new {Offset = x.Match.EpisodeOffsetSpecified ? x.Match.EpisodeOffset : 0, x.Match})
                .Where(x => x.Offset <= tvdb.Index)
                .OrderByDescending(x => x.Offset)
                .FirstOrDefault();

            if (seasonMatch != null)
            {
                return new AnidbEpisode
                {
                    Series = seasonMatch.Match.AnidbId,
                    Season = 1,
                    Index = tvdb.Index - seasonMatch.Offset
                };
            }

            // absolute episode numbers match
            var absolute = animeList.FirstOrDefault(x => x.DefaultTvdbSeason == "a");
            if (absolute != null)
            {
                return new AnidbEpisode
                {
                    Series = absolute.AnidbId,
                    Season = 1,
                    Index = tvdb.Index
                };
            }

            return null;
        }
        private int?FindTvdbEpisodeMapping(TvdbEpisode tvdb, AnimelistMapping mapping)
        {
            var maps  = GetEpisodeMappings(mapping);
            var exact = maps.FirstOrDefault(x => x.Tvdb == tvdb.Index);

            if (exact != null)
            {
                return(exact.Anidb);
            }

            if (mapping.OffsetSpecified)
            {
                var startInRange = !mapping.StartSpecified || (mapping.Start + mapping.Offset) <= tvdb.Index;
                var endInRange   = !mapping.EndSpecified || (mapping.End + mapping.Offset) >= tvdb.Index;

                if (startInRange && endInRange)
                {
                    return(tvdb.Index - mapping.Offset);
                }
            }

            return(null);
        }
        private int? FindTvdbEpisodeMapping(TvdbEpisode tvdb, AnimelistMapping mapping)
        {
            var maps = GetEpisodeMappings(mapping);
            var exact = maps.FirstOrDefault(x => x.Tvdb == tvdb.Index);

            if (exact != null)
                return exact.Anidb;

            if (mapping.OffsetSpecified)
            {
                var startInRange = !mapping.StartSpecified || (mapping.Start + mapping.Offset) <= tvdb.Index;
                var endInRange = !mapping.EndSpecified || (mapping.End + mapping.Offset) >= tvdb.Index;

                if (startInRange && endInRange)
                    return tvdb.Index - mapping.Offset;
            }

            return null;
        }
        public AnidbEpisode ToAnidb(TvdbEpisode tvdb)
        {
            List <AnimelistAnime> animeList;

            if (!_tvdbMappings.TryGetValue(tvdb.Series, out animeList))
            {
                return(null);
            }

            // look for exact mapping in mapping list
            foreach (var anime in animeList.Where(x => x.Mappinglist != null))
            {
                var mappings = anime.Mappinglist.Where(x => x.TvdbSeason == tvdb.Season);
                foreach (var mapping in mappings)
                {
                    var episode = FindTvdbEpisodeMapping(tvdb, mapping);

                    if (episode != null)
                    {
                        return(new AnidbEpisode
                        {
                            Series = anime.AnidbId,
                            Season = mapping.AnidbSeason,
                            Index = episode.Value
                        });
                    }
                }
            }

            var seasonMatch = animeList
                              .Select(x => new { Season = Parse(x.DefaultTvdbSeason), Match = x })
                              .Where(x => x.Season == tvdb.Season)
                              .Select(x => new { Offset = x.Match.EpisodeOffsetSpecified ? x.Match.EpisodeOffset : 0, x.Match })
                              .Where(x => x.Offset <= tvdb.Index)
                              .OrderByDescending(x => x.Offset)
                              .FirstOrDefault();

            if (seasonMatch != null)
            {
                return(new AnidbEpisode
                {
                    Series = seasonMatch.Match.AnidbId,
                    Season = 1,
                    Index = tvdb.Index - seasonMatch.Offset
                });
            }

            // absolute episode numbers match
            var absolute = animeList.FirstOrDefault(x => x.DefaultTvdbSeason == "a");

            if (absolute != null)
            {
                return(new AnidbEpisode
                {
                    Series = absolute.AnidbId,
                    Season = 1,
                    Index = tvdb.Index
                });
            }

            return(null);
        }