public IActionResult CreatePlaylist([FromBody] GeneratePlaylistDTO model)
        {
            if (model == null)
            {
                return(BadRequest());
            }

            var userId = int.Parse(userManager.GetUserId(HttpContext.User));

            var generatePaylistDTO = new GeneratePlaylistDTO
            {
                StartLocation   = model.StartLocation,
                Destination     = model.Destination,
                PlaylistName    = model.PlaylistName,
                RepeatArtist    = model.RepeatArtist,
                UseTopTracks    = model.UseTopTracks,
                GenrePercentage = model.GenrePercentage,
                UserId          = userId
            };

            var playlist = this.generateService.GeneratePlaylist(generatePaylistDTO).Result;

            if (playlist == null)
            {
                return(BadRequest());
            }

            var playlistWithImage = this.playlistService.AttachImage(playlist).Result;

            return(Created("post", playlistWithImage));
        }
        public async Task <IActionResult> Test()
        {
            //var add = await this._playlistService.AddPlaylistToFavoritesAsync(90, 1);
            //var remove = await this._playlistService.RemovePlaylistFromFavoritesAsync(90, 1);
            //var addAgain = await this._playlistService.AddPlaylistToFavoritesAsync(90, 1);

            //List<string> genres = new List<string>() { "jazz" };
            //List<int> durations = new List<int> { 0, 18767 };
            //var playlists = await this._playlistService.GetAllPlaylistsAsync();
            //var playlist1 = this._playlistService.FilterPlaylistsByName("Plovdiv", playlists);
            //var playlist2 = await this._playlistService.FilterPlaylistsByGenreAsync(genres, playlist1);
            //var playlist3 = this._playlistService.FilterPlaylistsByDuration(durations, playlist2);
            //var playlistsMaster = await this._playlistService.FilterPlaylistsMasterAsync("Plovdiv", genres, durations);

            //    public int Id { get; set; }
            //public string Title { get; set; }
            //public Dictionary<string, int> GenrePercentage { get; set; }
            //public User User { get; set; }
            //public int UserId { get; set; }

            //var editPlaylistDTO = new EditPlaylistDTO
            //{
            //    Id = 88,
            //    Title = "To the mountain",
            //    GenrePercentage = new Dictionary<string, int> { { "pop", 50 }, { "jazz", 50 } },
            //    UserId = 2
            //};

            //var playlist = await this._playlistService.EditPlaylistAsync(editPlaylistDTO);

            var playlist = new GeneratePlaylistDTO()
            {
                StartLocation   = "Sofia",
                Destination     = "Ihtiman",
                PlaylistName    = "Ihtiman",
                RepeatArtist    = true,
                UseTopTracks    = true,
                GenrePercentage = new Dictionary <string, int>()
                {
                    {
                        "rock", 20
                    },
                    {
                        "metal", 40
                    },
                    {
                        "pop", 20
                    },
                    {
                        "jazz", 20
                    }
                },
                UserId = 2
            };

            var returnedPlaylist = await this._generatePlaylistService.GeneratePlaylist(playlist);

            return(RedirectToAction(nameof(Index)));
        }
        public async Task <IActionResult> Create([Bind("Title," +
                                                       "StartLocationName, DestinationName," +
                                                       "RepeatArtist, TopTracks," +
                                                       "MetalPercentage, RockPercentage, PopPercentage, JazzPercentage")]
                                                 GeneratePlaylistViewModel genPlView)
        {
            if ((genPlView.MetalPercentage + genPlView.RockPercentage +
                 genPlView.PopPercentage + genPlView.JazzPercentage) > 100)
            {
                return(RedirectToAction("Create", "Playlists", new { error = TempData["Error"] = "Combined genre percentage must not exceed 100%" }));
            }

            var userId = int.Parse(userManager.GetUserId(HttpContext.User));

            var genres = new Dictionary <string, int>();

            genres.Add("metal", genPlView.MetalPercentage);
            genres.Add("rock", genPlView.RockPercentage);
            genres.Add("pop", genPlView.PopPercentage);
            genres.Add("jazz", genPlView.JazzPercentage);

            if (ModelState.IsValid)
            {
                var genPlaylistDTO = new GeneratePlaylistDTO()
                {
                    PlaylistName    = genPlView.Title,
                    StartLocation   = genPlView.StartLocationName,
                    Destination     = genPlView.DestinationName,
                    RepeatArtist    = genPlView.RepeatArtist,
                    UseTopTracks    = genPlView.TopTracks,
                    GenrePercentage = genres,
                    UserId          = userId
                };

                PlaylistDTO playlistDTO = await generateService.GeneratePlaylist(genPlaylistDTO);

                if (playlistDTO == null)
                {
                    throw new ArgumentNullException("Something went wrong with playlist creation.");
                }

                var playlistDtoWithImg = await this.service.AttachImage(playlistDTO);


                return(RedirectToAction("Details", new { id = playlistDtoWithImg.Id }));
            }

            return(RedirectToAction("Index", new { error = TempData["Error"] = "Playlist creation failed." }));
        }
        /// <summary>
        /// Generates playlist corresponding to user's input and calls supporting methods to generate a collection of tracks,
        /// finetune its duration, and set different properties of the playlist. Then the playlist is saved in the database.
        /// </summary>
        /// <param name="playlistDTO">DTO with all user's input needed for playlist generation</param>
        /// <returns>DTO of the created playlist</returns>
        public async Task <PlaylistDTO> GeneratePlaylist(GeneratePlaylistDTO playlistDTO)
        {
            double travelDuration = await GetTravelDuration(playlistDTO.StartLocation, playlistDTO.Destination);

            List <Track> tracks = new List <Track>();

            if (playlistDTO.UseTopTracks)
            {
                tracks.AddRange(GetTopTracks("rock", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
                tracks.AddRange(GetTopTracks("metal", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
                tracks.AddRange(GetTopTracks("pop", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
                tracks.AddRange(GetTopTracks("jazz", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
            }
            else
            {
                tracks.AddRange(GetTracks("rock", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
                tracks.AddRange(GetTracks("metal", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
                tracks.AddRange(GetTracks("pop", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
                tracks.AddRange(GetTracks("jazz", travelDuration, playlistDTO.GenrePercentage, playlistDTO.RepeatArtist).Result);
            }

            List <Track> finalPlaylist = FinetunePlaytime(travelDuration, tracks, playlistDTO.GenrePercentage).ToList();
            double       playtime      = CalculatePlaytime(finalPlaylist);

            var playlist = new Playlist()
            {
                User             = playlistDTO.User,
                UserId           = playlistDTO.UserId,
                Title            = playlistDTO.PlaylistName,
                UseTopTracks     = playlistDTO.UseTopTracks,
                RepeatArtist     = playlistDTO.RepeatArtist,
                StartLocation    = playlistDTO.StartLocation,
                Destination      = playlistDTO.Destination,
                TravelDuration   = travelDuration,
                PlaylistPlaytime = playtime,
                PlaytimeString   = GetPlaytimeString((int)playtime),
                Rank             = CalculateRank(finalPlaylist),
                CreatedOn        = this.dateTimeProvider.GetDateTime()
            };

            await this.context.Playlists.AddAsync(playlist);

            await this.context.SaveChangesAsync();

            var playlistFromDb = this.context.Playlists.FirstOrDefault(x => x.Title == playlist.Title);

            if (playlistFromDb == null)
            {
                throw new ArgumentNullException("Playlist not found in the database.");
            }

            List <PlaylistTrack> playlistTracks = finalPlaylist.Select(x => new PlaylistTrack(x.Id, playlistFromDb.Id)).ToList();

            playlistFromDb.TracksCount = playlistTracks.Count;

            List <string> genresStringList = playlistDTO.GenrePercentage.Where(x => x.Value > 0).Select(y => y.Key).ToList();

            List <Genre> genres = this.context.Genres.Where(x => genresStringList.Contains(x.Name)).ToList();

            List <PlaylistGenre> playlistGenres = genres.Select(x => new PlaylistGenre(x.Id, playlistFromDb.Id)).ToList();

            playlistFromDb.GenresCount = genres.Count;

            await this.context.PlaylistTracks.AddRangeAsync(playlistTracks);

            await this.context.PlaylistGenres.AddRangeAsync(playlistGenres);

            await this.context.SaveChangesAsync();

            return(new PlaylistDTO(playlist));
        }