protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            UserSeriesDetailViewModel viewModel = (UserSeriesDetailViewModel)validationContext.ObjectInstance;

            var maxProperty = validationContext.ObjectType.GetProperty(_maxPropertyName);

            if (maxProperty == null)
            {
                return(new ValidationResult(string.Format("Unknown property {0}", _maxPropertyName)));
            }

            var maxValue = (int)maxProperty.GetValue(validationContext.ObjectInstance, null);

            if (viewModel.SeasonsWatched < 0 || viewModel.SeasonsWatched > maxValue)
            {
                return(new ValidationResult("Incorrect number of seasons"));
            }

            return(ValidationResult.Success);
        }
        // GET: Series/Details/5
        public async Task <IActionResult> Details(UserSeriesDetailViewModel viewModel)
        {
            Series series = null;

            if (ModelState.IsValid)
            {
                string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

                var userSeries =
                    await _context.UsersSeries.FirstOrDefaultAsync(x =>
                                                                   x.UserId == userId && x.SeriesId == viewModel.SeriesId);

                var favouriteSeries =
                    await _context.FavoritesSeries.FirstOrDefaultAsync(x => x.UserId == userId && x.SeriesId == viewModel.SeriesId);

                if (favouriteSeries == null && viewModel.IsFavourite)
                {
                    var newFavoritesSeries = new FavoritesSeries
                    {
                        SeriesId  = viewModel.SeriesId,
                        UserId    = userId,
                        CreatedAt = DateTime.UtcNow,
                        CreatedBy = userId
                    };

                    _context.FavoritesSeries.Add(newFavoritesSeries);
                    await _context.SaveChangesAsync();
                }
                else if (favouriteSeries != null && !viewModel.IsFavourite)
                {
                    _context.FavoritesSeries.Remove(favouriteSeries);
                    await _context.SaveChangesAsync();
                }

                if (userSeries == null)
                {
                    userSeries = new UserSeries
                    {
                        SeriesId        = viewModel.SeriesId,
                        UserId          = userId,
                        Rating          = (int)viewModel.SeriesRating,
                        WatchStatus     = viewModel.WatchStatus,
                        CreatedBy       = userId,
                        CreatedAt       = DateTime.UtcNow,
                        EpisodesWatched = viewModel.EpisodesWatched,
                        SeasonsWatched  = viewModel.SeasonsWatched,
                    };

                    _context.Add(userSeries);


                    if (viewModel.SeriesRating != SeriesRating.NotRated)
                    {
                        series = await _context.Series.FirstOrDefaultAsync(x => x.Id == viewModel.SeriesId);

                        series.UserVotes++;
                        var seriesRating = series.SeriesUsers.Sum(x => x.Rating);
                        series.UserRating = (decimal)seriesRating / series.UserVotes;
                        _context.Update(series);
                    }
                }
                else
                {
                    userSeries.WatchStatus = viewModel.WatchStatus;
                    userSeries.Rating      = (int)viewModel.SeriesRating;

                    series = await _context.Series
                             .Include(x => x.SeriesGenres)
                             .ThenInclude(x => x.Genre)
                             .FirstOrDefaultAsync(x => x.Id == viewModel.SeriesId);

                    if (userSeries.Rating != 0 && series.UserVotes != 0)
                    {
                        var seriesRating = series.SeriesUsers.Sum(x => x.Rating);
                        series.UserRating = (decimal)seriesRating / series.UserVotes;
                    }

                    _context.Update(series);
                    _context.Update(userSeries);
                }

                await _context.SaveChangesAsync();

                return(RedirectToAction("Details", new { id = viewModel.SeriesId }));
            }
            else
            {
                series = await _context.Series
                         .Include(x => x.SeriesGenres)
                         .ThenInclude(x => x.Genre)
                         .FirstOrDefaultAsync(x => x.Id == viewModel.SeriesId);

                viewModel.SiteRating    = series.UserRating;
                viewModel.PosterContent = series.PosterContent;

                viewModel.Genres = new List <Genre>();

                foreach (var seriesGenre in series.SeriesGenres)
                {
                    viewModel.Genres.Add(seriesGenre.Genre);
                }

                return(View(viewModel));
            }
        }
        // GET: Series/Details/5
        public async Task <IActionResult> Details(long?id)
        {
            if (id == null)
            {
                return(NotFound());
            }

            string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

            var series = await _context.Series.Include(x => x.Seasons)
                         .Include(x => x.SeriesCharacters)
                         .Include(x => x.Crews)
                         .Include(x => x.SeriesReviews)
                         .ThenInclude(x => x.UserReviews)
                         .Include(x => x.SeriesGenres)
                         .ThenInclude(x => x.Genre)
                         .FirstOrDefaultAsync(m => m.Id == id);

            if (series == null)
            {
                return(NotFound());
            }


            // TODO move to mapper
            var viewModel = new UserSeriesDetailViewModel
            {
                SeriesId         = series.Id,
                Name             = series.Name,
                OriginalName     = series.OriginalName,
                SiteRating       = series.UserRating,
                UserVotes        = series.UserVotes,
                Overview         = series.Overview,
                Status           = series.Status,
                AiredFrom        = series.AiredFrom,
                AiredTo          = series.AiredTo,
                AirDayOfWeek     = series.AirDayOfWeek,
                AirTime          = series.AirTime,
                NumberOfSeasons  = series.NumberOfSeasons,
                NumberOfEpisodes = series.NumberOfEpisodes,
                EpisodeRuntime   = series.EpisodeRuntime,
                TotalRuntime     = series.TotalRuntime,
                PosterContent    = series.PosterContent,
                Genres           = new List <Genre>(),
                SeasonSeries     = new List <SeasonSeriesDetailViewModel>(),
                Cast             = new List <CastSeriesDetailViewModel>(),
                Crew             = new List <CrewSeriesDetailViewModel>(),
                Reviews          = new List <SeriesReviewDetailViewModel>()
            };

            // GENRES
            foreach (var seriesGenre in series.SeriesGenres)
            {
                viewModel.Genres.Add(seriesGenre.Genre);
            }

            //SEASONS
            var seasonsOnView = 5;
            var seasons       = series.Seasons.OrderBy(x => x.SeasonNumber).ToList();

            for (int i = 0; i < seasonsOnView; i++)
            {
                if (i < seasons.Count)
                {
                    var season          = seasons.ElementAt(i);
                    var seasonViewModel = new SeasonSeriesDetailViewModel
                    {
                        SeasonId         = season.Id,
                        NumberOfEpisodes = season.NumberOfEpisodes,
                        SeasonName       = season.Name,
                        SeasonNumber     = season.SeasonNumber,
                    };
                    if (season.AiredFrom != null)
                    {
                        seasonViewModel.AiredFrom = season.AiredFrom.Value.ToString("dd MMMM yyyy");
                    }

                    viewModel.SeasonSeries.Add(seasonViewModel);
                }
                else
                {
                    break;
                }
            }


            viewModel.IsMoreSeasons = seasons.Count > viewModel.SeasonSeries.Count;

            //CAST

            for (int i = 0; i < 4; i++)
            {
                if (i < series.SeriesCharacters.Count)
                {
                    var characterId = series.SeriesCharacters.ElementAt(i).CharacterId;
                    var castMember  = await _context.Characters
                                      .Include(x => x.Person)
                                      .FirstOrDefaultAsync(x => x.Id == characterId);

                    var castViewModel = new CastSeriesDetailViewModel
                    {
                        PersonId  = castMember.PersonId,
                        Character = castMember.Name,
                        Name      = castMember.Person.Name,
                        Picture   = castMember.Person.PosterContent
                    };

                    viewModel.Cast.Add(castViewModel);
                }
                else
                {
                    break;
                }
            }

            viewModel.IsMoreCast = series.SeriesCharacters.Count > viewModel.Cast.Count;

            // Crew

            for (int i = 0; i < 4; i++)
            {
                if (i < series.Crews.Count)
                {
                    var crew     = series.Crews.ElementAt(i);
                    var personId = crew.PersonId;
                    var person   = await _context.Persons
                                   .FirstOrDefaultAsync(x => x.Id == personId);

                    var crewViewModel = new CrewSeriesDetailViewModel
                    {
                        PersonId   = personId,
                        Name       = person.Name,
                        Job        = crew.Job,
                        Department = crew.Department,
                        Picture    = person.PosterContent
                    };

                    viewModel.Crew.Add(crewViewModel);
                }
                else
                {
                    break;
                }
            }

            viewModel.IsMoreCrew = series.Crews.Count > viewModel.Crew.Count;

            // REVIEWS

            for (int i = 0; i < 3; i++)
            {
                if (i < series.SeriesReviews.Count)
                {
                    var review = series.SeriesReviews.ElementAt(i);

                    var reviewViewModel = new SeriesReviewDetailViewModel()
                    {
                        Id        = review.Id,
                        Content   = review.Content,
                        Likes     = review.Likes,
                        WrittenOn = review.CreatedAt
                    };

                    if (review.LastChangedAt != null)
                    {
                        reviewViewModel.WrittenOn = review.LastChangedAt.Value;
                    }

                    var user = await _userManager.FindByIdAsync(review.UserId);

                    reviewViewModel.Username = user.UserName;

                    var userRating = await _context.UsersSeries
                                     .Where(x => x.SeriesId == id && x.UserId == user.Id)
                                     .FirstOrDefaultAsync();

                    if (userRating != null)
                    {
                        reviewViewModel.Rating = userRating.Rating;
                    }

                    reviewViewModel.IsRated = review.UserReviews.Where(x => x.UserId == userId).Any();

                    viewModel.Reviews.Add(reviewViewModel);
                }
                else
                {
                    break;
                }
            }


            if (userId != null)
            {
                var review =
                    await _context.SeriesReviews.FirstOrDefaultAsync(x => x.UserId == userId && x.SeriesId == id);

                if (review != null)
                {
                    viewModel.IsReviewWritten = true;
                    viewModel.ReviewId        = review.Id;
                }

                var userSeries = await _context.UsersSeries.FirstOrDefaultAsync(x => x.UserId == userId && x.SeriesId == id);

                if (userSeries != null)
                {
                    viewModel.WatchStatus     = userSeries.WatchStatus;
                    viewModel.SeriesRating    = (SeriesRating)userSeries.Rating;
                    viewModel.SeasonsWatched  = userSeries.SeasonsWatched;
                    viewModel.EpisodesWatched = userSeries.EpisodesWatched;
                }

                var favouriteSeries =
                    await _context.FavoritesSeries.FirstOrDefaultAsync(x => x.UserId == userId && x.SeriesId == id);

                viewModel.IsFavourite = favouriteSeries != null;
            }

            return(View(viewModel));
        }