//Creates a new playlist and populates it
        public async Task <ActionResult> NewPlaylist(AdvTrack playCreate)
        {
            //TODO populate playlist
            //Like previous spotify app
            //Based on genre BPM, etc

            //https://api.spotify.com/v1/recommendations/available-genre-seeds
            //https://api.spotify.com/v1/recommendations
            //using artists/genre seeds
            //get tracks to populate the playlist with
            var tracks = await PopulatePlaylist(playCreate);

            //create playlist after getting tracks in case there is an error
            var playlist = await CreateNewPlaylist(playCreate);

            var p = await AddTracksToPlaylist(tracks, playlist.Id);

            return(RedirectToAction("ViewPlaylist", "Home", new { href = playlist.Id }));
        }
        //TODO Doesn't work with songs same artist
        public AdvTrack RecommendationEngine(List <AdvTrack> advTracks)
        {
            var math = new AdvTrack()
            {
                Instrumentalness = 0,
                Liveness         = 0,
                Loudness         = 0,
                Energy           = 0,
                Danceability     = 0,
                Speechiness      = 0,
                Valence          = 0
            };

            //Figure out how to analyze the tracks
            //would need standard deviation, mean, etc
            //Would pass in advtrack data
            foreach (var adv in advTracks)
            {
                math.Instrumentalness += adv.Instrumentalness;
                math.Liveness         += adv.Liveness;
                math.Loudness         += adv.Loudness;
                math.Energy           += adv.Energy;
                math.Danceability     += adv.Danceability;
                math.Speechiness      += adv.Speechiness;
                math.Valence          += adv.Valence;
            }
            //start with averages
            //then add in some noticeable outliers

            math.Instrumentalness /= advTracks.Count;
            math.Liveness         /= advTracks.Count;
            math.Loudness         /= advTracks.Count;
            math.Energy           /= advTracks.Count;
            math.Danceability     /= advTracks.Count;
            math.Speechiness      /= advTracks.Count;
            math.Valence          /= advTracks.Count;

            return(math);
        }
        //TODO
        public async Task <ActionResult> GetRecsFromPlaylist(string href)
        {
            var trackRec = new AdvTrack();
            var tempList = new List <Track>();
            var user     = await GetCurrentUser();

            var listTracks = await GetPlaylistTracks("https://api.spotify.com/v1/playlists/2Ql3TagKirJQJDG93GqMiE");

            var trackIds = new List <string>();

            //analyze each track in a playlist
            foreach (var t in listTracks)
            {
                trackIds.Add(t.Track.Id);
            }
            var audioFeat = await GetAudioFeatures(trackIds.ToArray());

            //GetAudioFeatures
            //send to recommendationengine
            trackRec = RecommendationEngine(audioFeat);
            //would be running Populateplaylist multiple times
            foreach (var t in listTracks)
            {
                trackRec.Artist = t.Track.Artists.FirstOrDefault().Name;
                //need to think of a better way to do this, want to prevent duplicates somehow
                tempList.AddRange(await PopulatePlaylist(trackRec, 1));
            }
            var pc = new PlayCreate()
            {
                Name   = "Test 4",
                UserId = user.Id
            };
            var newList = await CreateNewPlaylist(pc);

            var x = await AddTracksToPlaylist(tempList, newList.Id);

            return(RedirectToAction("ViewPlaylist", "Home", new { href = newList.Id }));;
        }
        //Playlist creation from Audio Features
        public async Task <ActionResult> NewAdvPlaylist(AdvTrackCalc adv)
        {
            var g = adv.GenreList.ToArray();

            var user = await GetCurrentUser();

            var advTrack = new AdvTrack()
            {
                Acousticness     = adv.AvgAcousticness,
                Danceability     = adv.AvgDance,
                Energy           = adv.AvgEnergy,
                Instrumentalness = adv.AvgInstrumentalness,
                Liveness         = adv.AvgLiveness,
                Loudness         = adv.AvgLoudness,
                Speechiness      = adv.AvgSpeechiness,
                Tempo            = adv.AvgTempo,
                Valence          = adv.AvgValence,
                UserId           = user.Id,
                GenreList        = adv.GenreList,
                Genre            = string.Join(",", g)
            };

            return(PartialView("_AdvTrackFeatures", advTrack));
        }
        //Helper functions for Spotify API
        #region Helpers

        //Param Dictionary Builder, could also use max/min instead of target
        public async Task <Dictionary <string, string> > BuildRecParamDict(AdvTrack a)
        {
            var paramDict = new Dictionary <string, string>()
            {
                { "limit", "100" }
            };

            if (a.Genre != null && a.Genre.Trim() != "")
            {
                paramDict.Add("seed_genres", a.Genre);
            }
            if (a.Artist != null && a.Artist.Trim() != "")
            {
                paramDict.Add("seed_artists", await GetSingleArtist(a.Artist));
            }
            if (a.Acousticness != null)
            {
                paramDict.Add("target_acousticness", a.Acousticness.ToString());
            }
            if (a.Danceability != null)
            {
                paramDict.Add("target_danceability", a.Danceability.ToString());
            }
            if (a.Energy != null)
            {
                paramDict.Add("target_energy", a.Energy.ToString());
            }
            if (a.Instrumentalness != null)
            {
                paramDict.Add("target_instrumentalness", a.Instrumentalness.ToString());
            }
            if (a.Key != null)
            {
                paramDict.Add("target_key", a.Key.ToString());
            }
            if (a.Liveness != null)
            {
                paramDict.Add("target_liveness", a.Liveness.ToString());
            }
            if (a.Loudness != null)
            {
                paramDict.Add("target_loudness", a.Loudness.ToString());
            }
            if (a.Mode != null)
            {
                paramDict.Add("target_mode", a.Mode.ToString());
            }
            if (a.Speechiness != null)
            {
                paramDict.Add("target_speechiness", a.Speechiness.ToString());
            }
            if (a.Tempo != null)
            {
                paramDict.Add("target_tempo", a.Tempo.ToString());
            }
            if (a.Time_signature != null)
            {
                paramDict.Add("target_time_signature", a.Time_signature.ToString());
            }
            if (a.Valence != null)
            {
                paramDict.Add("target_valence", a.Valence.ToString());
            }

            return(paramDict);
        }
        /// <summary>
        /// GETS tracks recommended by spotify based on the supplied criteria
        /// </summary>
        /// <param name="playCreate">Playlist info</param>
        /// <returns>List of track objects</returns>
        public async Task <List <Track> > PopulatePlaylist(AdvTrack playCreate, int limit = 0)
        {
            //set a default length
            var totalTime = playCreate.Length <= 0 ? 3600000 : 60000 * playCreate.Length;
            var trackList = new List <Track>();
            var getString = "https://api.spotify.com/v1/recommendations";

            //need to replace selected genres with closest match.
            //LoadAndReplaceGenres(playCreate.Genre)

            var genreString = "https://api.spotify.com/v1/recommendations/available-genre-seeds";

            var response = await SpotApi(HttpMethod.Get, genreString);

            var j          = JsonConvert.DeserializeObject <GenreList>(response).Genres.ToList <string>();
            var splitGenre = playCreate.Genre.Replace(" ", "-").Split(',').ToList <string>();
            var genreList  = "";

            foreach (var genre in j.ToList <string>())
            {
                foreach (var g in splitGenre.ToList <string>())
                {
                    if (g == genre)
                    {
                        genreList += g + ",";
                    }
                }
            }

            if (genreList == "")
            {
                foreach (var genre in j)
                {
                    foreach (var g in splitGenre)
                    {
                        if (g.Contains(genre) && !genreList.Contains(genre))
                        {
                            genreList += genre + ",";
                        }
                    }
                }
            }

            playCreate.Genre = genreList;

            var paramDict = await BuildRecParamDict(playCreate);

            //get recommended tracks based on seeds
            var res = await SpotApi(HttpMethod.Get, getString, paramDict);

            var list = JsonConvert.DeserializeObject <SeedResult>(res).Tracks.ToList();

            if (limit == 0)
            {
                foreach (var l in list)
                {
                    if (totalTime > 0)
                    {
                        trackList.Add(l);
                    }
                    totalTime -= l.Duration_Ms;
                }
            }
            else
            {
                foreach (var l in list)
                {
                    if (limit > 0)
                    {
                        trackList.Add(l);
                    }
                    limit--;
                }
            }
            return(trackList);
        }