private Contract_AniDBAnime GenerateContract(List<AniDB_Anime_Title> titles, DefaultAnimeImages defaultImages,
            List<Contract_AniDB_Character> characters, IEnumerable<MovieDB_Fanart> movDbFanart, IEnumerable<TvDB_ImageFanart> tvDbFanart,
            IEnumerable<TvDB_ImageWideBanner> tvDbBanners)
        {
            Contract_AniDBAnime contract = new Contract_AniDBAnime();
            contract.AirDate = this.AirDate;
            contract.AllCinemaID = this.AllCinemaID;

            //TODO this can
            contract.AllTags =
                new HashSet<string>(
                    this.AllTags.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries)
                        .Select(a => a.Trim())
                        .Where(a => !string.IsNullOrEmpty(a)), StringComparer.InvariantCultureIgnoreCase);
            contract.AllTitles =
                new HashSet<string>(
                    this.AllTitles.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries)
                        .Select(a => a.Trim())
                        .Where(a => !string.IsNullOrEmpty(a)), StringComparer.InvariantCultureIgnoreCase);
            contract.AnimeID = this.AnimeID;
            contract.AnimeNfo = this.AnimeNfo;
            contract.AnimePlanetID = this.AnimePlanetID;
            contract.AnimeType = this.AnimeType;
            contract.ANNID = this.ANNID;
            contract.AvgReviewRating = this.AvgReviewRating;
            contract.AwardList = this.AwardList;
            contract.BeginYear = this.BeginYear;
            contract.Description = this.Description;
            contract.DateTimeDescUpdated = this.DateTimeDescUpdated;
            contract.DateTimeUpdated = this.DateTimeUpdated;
            contract.EndDate = this.EndDate;
            contract.EndYear = this.EndYear;
            contract.EpisodeCount = this.EpisodeCount;
            contract.EpisodeCountNormal = this.EpisodeCountNormal;
            contract.EpisodeCountSpecial = this.EpisodeCountSpecial;
            contract.ImageEnabled = this.ImageEnabled;
            contract.LatestEpisodeNumber = this.LatestEpisodeNumber;
            contract.MainTitle = this.MainTitle;
            contract.Picname = this.Picname;
            contract.Rating = this.Rating;
            contract.Restricted = this.Restricted;
            contract.ReviewCount = this.ReviewCount;
            contract.TempRating = this.TempRating;
            contract.TempVoteCount = this.TempVoteCount;
            contract.URL = this.URL;
            contract.VoteCount = this.VoteCount;
            contract.FormattedTitle = GetFormattedTitle(titles);
            contract.DisableExternalLinksFlag = this.DisableExternalLinksFlag;
            contract.Characters = characters;

            if (defaultImages != null)
            {
                contract.DefaultImageFanart = defaultImages.Fanart?.ToContract();
                contract.DefaultImagePoster = defaultImages.Poster?.ToContract();
                contract.DefaultImageWideBanner = defaultImages.WideBanner?.ToContract();
            }

            if (AnimeTypeEnum == enAnimeType.Movie)
            {
                contract.Fanarts = movDbFanart?.Select(a => new Contract_AniDB_Anime_DefaultImage
                    {
                        ImageType = (int)JMMImageType.MovieDB_FanArt,
                        MovieFanart = a.ToContract(),
                        AniDB_Anime_DefaultImageID = a.MovieDB_FanartID
                    })
                    .ToList();
            }
            else // Not a movie
            {
                contract.Fanarts = tvDbFanart?.Select(a => new Contract_AniDB_Anime_DefaultImage
                    {
                        ImageType = (int)JMMImageType.TvDB_FanArt,
                        TVFanart = a.ToContract(),
                        AniDB_Anime_DefaultImageID = a.TvDB_ImageFanartID
                    })
                    .ToList();
                contract.Banners = tvDbBanners?.Select(a => new Contract_AniDB_Anime_DefaultImage
                    {
                        ImageType = (int)JMMImageType.TvDB_Banner,
                        TVWideBanner = a.ToContract(),
                        AniDB_Anime_DefaultImageID = a.TvDB_ImageWideBannerID
                    })
                    .ToList();
            }

            if (contract.Fanarts?.Count == 0) contract.Fanarts = null;
            if (contract.Banners?.Count == 0) contract.Banners = null;

            return contract;
        }
        public Dictionary<int, DefaultAnimeImages> GetDefaultImagesByAnime(int[] animeIds)
        {

            if (animeIds == null)
                throw new ArgumentNullException("animeIds");

            var defImagesByAnime = new Dictionary<int, DefaultAnimeImages>();

            if (animeIds.Length == 0) return defImagesByAnime;


                // TODO: Determine if joining on the correct columns
                var results = session.CreateSQLQuery(@"
                SELECT {defImg.*}, {tvWide.*}, {tvPoster.*}, {tvFanart.*}, {movPoster.*}, {movFanart.*}
                    FROM AniDB_Anime_DefaultImage defImg
                        LEFT OUTER JOIN TvDB_ImageWideBanner AS tvWide
                            ON tvWide.TvDB_ImageWideBannerID = defImg.ImageParentID AND defImg.ImageParentType = :tvdbBannerType
                        LEFT OUTER JOIN TvDB_ImagePoster AS tvPoster
                            ON tvPoster.TvDB_ImagePosterID = defImg.ImageParentID AND defImg.ImageParentType = :tvdbCoverType
                        LEFT OUTER JOIN TvDB_ImageFanart AS tvFanart
                            ON tvFanart.TvDB_ImageFanartID = defImg.ImageParentID AND defImg.ImageParentType = :tvdbFanartType
                        LEFT OUTER JOIN MovieDB_Poster AS movPoster
                            ON movPoster.MovieDB_PosterID = defImg.ImageParentID AND defImg.ImageParentType = :movdbPosterType
                        LEFT OUTER JOIN MovieDB_Fanart AS movFanart
                            ON movFanart.MovieDB_FanartID = defImg.ImageParentID AND defImg.ImageParentType = :movdbFanartType
                    WHERE defImg.AnimeID IN (:animeIds) AND defImg.ImageParentType IN (:tvdbBannerType, :tvdbCoverType, :tvdbFanartType, :movdbPosterType, :movdbFanartType)")
                    .AddEntity("defImg", typeof(AniDB_Anime_DefaultImage))
                    .AddEntity("tvWide", typeof(TvDB_ImageWideBanner))
                    .AddEntity("tvPoster", typeof(TvDB_ImagePoster))
                    .AddEntity("tvFanart", typeof(TvDB_ImageFanart))
                    .AddEntity("movPoster", typeof(MovieDB_Poster))
                    .AddEntity("movFanart", typeof(MovieDB_Fanart))
                    .SetParameterList("animeIds", animeIds)
                    .SetInt32("tvdbBannerType", (int) ImageEntityType.TvDB_Banner)
                    .SetInt32("tvdbCoverType", (int) ImageEntityType.TvDB_Cover)
                    .SetInt32("tvdbFanartType", (int) ImageEntityType.TvDB_FanArt)
                    .SetInt32("movdbPosterType", (int) ImageEntityType.MovieDB_Poster)
                    .SetInt32("movdbFanartType", (int) ImageEntityType.MovieDB_FanArt)
                    .List<object[]>();

                foreach (object[] result in results)
                {
                    var aniDbDefImage = (AniDB_Anime_DefaultImage) result[0];
                    IImageEntity parentImage = null;

                    switch ((ImageEntityType) aniDbDefImage.ImageParentType)
                    {
                        case ImageEntityType.TvDB_Banner:
                            parentImage = (IImageEntity) result[1];
                            break;
                        case ImageEntityType.TvDB_Cover:
                            parentImage = (IImageEntity) result[2];
                            break;
                        case ImageEntityType.TvDB_FanArt:
                            parentImage = (IImageEntity) result[3];
                            break;
                        case ImageEntityType.MovieDB_Poster:
                            parentImage = (IImageEntity) result[4];
                            break;
                        case ImageEntityType.MovieDB_FanArt:
                            parentImage = (IImageEntity) result[5];
                            break;
                    }

                    if (parentImage == null)
                    {
                        continue;
                    }

                    DefaultAnimeImage defImage = new DefaultAnimeImage(aniDbDefImage, parentImage);

                    if (!defImagesByAnime.TryGetValue(aniDbDefImage.AnimeID, out DefaultAnimeImages defImages))
                    {
                        defImages = new DefaultAnimeImages {AnimeID = aniDbDefImage.AnimeID};
                        defImagesByAnime.Add(defImages.AnimeID, defImages);
                    }

                    switch (defImage.AniDBImageSizeType)
                    {
                        case ImageSizeType.Poster:
                            defImages.Poster = defImage;
                            break;
                        case ImageSizeType.WideBanner:
                            defImages.WideBanner = defImage;
                            break;
                        case ImageSizeType.Fanart:
                            defImages.Fanart = defImage;
                            break;
                    }
                }
            }