import requests

import time 
import streamlit as st
import pandas as pd
import time
from datetime import datetime as dt
import datetime
import os

import pandas as pd
import numpy as np
import plotly.graph_objects as go

# Set up containers
header = st.beta_container()
yearlyData = st.beta_container()
topStuffData = st.beta_container()
JanuaryData = st.beta_container()
FebruaryData = st.beta_container()
MarchData = st.beta_container()
AprilData = st.beta_container()
MayData = st.beta_container()
JuneData = st.beta_container()
JulyData = st.beta_container()
AugustData = st.beta_container()
SeptemberData = st.beta_container()
OctoberData = st.beta_container()
NovemberData = st.beta_container()
DecemberData = st.beta_container()

def monthConvert(monthStr,year):
    if monthStr.lower() == 'january' or monthStr.lower() == 'jan':
        month = 1
        daysInMonth = 31
                
    elif monthStr.lower() == 'february' or monthStr.lower() == 'feb':
        month = 2
        if (year % 4) == 0:
            if (year % 100) == 0:
                if (year % 400) == 0:
                    daysInMonth = 29
                else: 
                    daysInMonth = 28
            else:
                daysInMonth = 29
        else:
            daysInMonth = 28
    elif monthStr.lower() == 'march' or monthStr.lower() == 'mar':
        month = 3
        daysInMonth = 31
    elif monthStr.lower() == 'april' or monthStr.lower() == 'apr':
        month = 4
        daysInMonth = 30
    elif monthStr.lower() == 'may' or monthStr.lower() == 'may':
        month = 5
        daysInMonth = 31
    elif monthStr.lower() == 'june' or monthStr.lower() == 'jun':
        month = 6
        daysInMonth = 30
    elif monthStr.lower() == 'july' or monthStr.lower() == 'jul':
        month = 7
        daysInMonth = 31
    elif monthStr.lower() == 'august' or monthStr.lower() == 'aug':
        month = 8
        daysInMonth = 31
    elif monthStr.lower() == 'september' or monthStr.lower() == 'sep':
        month = 9
        daysInMonth = 30
    elif monthStr.lower() == 'october' or monthStr.lower() == 'oct':
        month = 10
        daysInMonth = 31
    elif monthStr.lower() == 'november' or monthStr.lower() == 'nov':
        month = 11
        daysInMonth = 30
    elif monthStr.lower() == 'december' or monthStr.lower() == 'dec':
        month = 12
        daysInMonth = 31
    else:
        month = 0
        daysInMonth = 0
    return [month,daysInMonth]
def getYearUniTime(yearList):
    st.write("Mode 1: Current Year Data")
    st.write("Mode 2: Previous Year")
    st.write("Mode 3: Custom Time Frame")
    mode = int(st.selectbox("Choose mode 1-3",[1,2,3]))
    if mode == 1:
        today = dt.today()
        dateM = str(dt(today.year, today.month, 1))
        year = int(dateM[0:4])
        timeStart = time.mktime(datetime.datetime(year,1,1,0,0,0).timetuple())
        timeEnd = time.time()
    if mode == 2:
        if len(yearList) == 0:
            st.write("No data from previous years... displaying current year")
            mode = 1
        else:
            year = st.selectbox("Enter year",yearList)
            
            timeStart = time.mktime(datetime.datetime(year,1,1,0,0,0).timetuple())
            timeEnd = time.mktime(datetime.datetime(year,12,31,23,59,59).timetuple())
        
    if mode == 3:
        timeStart = time.mktime(st.date_input("Start Date").timetuple())
        timeEnd = time.mktime(st.date_input("End Date").timetuple())
    
    timeStart = format(timeStart, ".0f")
    timeEnd = format(timeEnd, ".0f")    
    floatTime = [timeStart,timeEnd]
    return [str(floatTime) for floatTime in floatTime]

def getUserData(pictureOrSTime):
    headers = {"user-agent": USER_AGENT}
    url = 'http://ws.audioscrobbler.com/2.0/'
    payload = {'method':'user.getInfo'}
    payload['user'] = USER_AGENT
    payload['api_key'] = API_KEY
    payload['format'] = 'json'
    response = requests.get(url,headers=headers, params=payload)
    data = response.json()
        
    if pictureOrSTime == 'picture':
        return data['user']['image'][2]['#text']
    else:
        timestamp = data['user']['registered']['#text']
        datetime = str(dt.fromtimestamp(timestamp))
        return int(datetime[:4])
def lastfm_weeklyChart(timeList,method):
    payload = {'method' : method}
    headers = {"user-agent": USER_AGENT}
    url = 'http://ws.audioscrobbler.com/2.0/'

    payload['user'] = USER_AGENT
    payload['api_key'] = API_KEY
    payload['format'] = 'json'
    payload['from'] = 	timeList[0]
    payload['to'] = timeList[1]
    response = requests.get(url,headers=headers, params=payload)
    return response.json()
API_KEY = str(os.environ.get('LASTFM_API_KEY')) #Environmental Variable to protect my API key
USER_AGENT = st.text_input("Enter Last Fm User Name")
if USER_AGENT != "":
    yearRegistered = getUserData('STime')
    countYear = yearRegistered
    today = dt.today()
    dateM = str(dt(today.year, today.month, 1))
    year = int(dateM[0:4])
    yearList = []
    while year > countYear:
        yearList.append(countYear)
        countYear += 1
    timeList = getYearUniTime(yearList)
st.write("wait for mode option before clicking")
continue_button = st.button("Press when ready")
if continue_button == True:
    st.write("Loading . . .")
    almost_year = time.ctime(int(timeList[0]))
    year = int(almost_year[-4:])
    data = lastfm_weeklyChart(timeList,'user.getWeeklyTrackChart')

    totalSongs = len(data['weeklytrackchart']['track'])
    
    songDict = {}
    for i in range(0,totalSongs):
        songDict[i] = {"Track":data['weeklytrackchart']['track'][i]['name'],"PlayCount":int(data['weeklytrackchart']['track'][i]['playcount'])
        ,"Artist":data['weeklytrackchart']['track'][i]['artist']['#text'],"Image":data['weeklytrackchart']['track'][i]['image'][2]['#text']}
    SongList = []
    ArtistList = []
    SongFreqList = []
    for k,v in songDict.items():
        SongList.append(songDict[k]["Track"])
        ArtistList.append(songDict[k]["Artist"])
        SongFreqList.append(songDict[k]["PlayCount"])
    data = {'Song Name' : SongList,'Artist':ArtistList,'PlayCount':SongFreqList}
    df = pd.DataFrame(data=data)
    df.index = np.arange(1,len(df)+1)

    #Artist Chart
    artistData = lastfm_weeklyChart(timeList,'user.getWeeklyArtistChart')
    totalArtists = len(artistData['weeklyartistchart']['artist'])

    artArtistList = []
    artistFreqList = []
    for i in range(0,totalArtists):
        artArtistList.append(artistData['weeklyartistchart']['artist'][i]['name'])
        artistFreqList.append(artistData['weeklyartistchart']['artist'][i]['playcount'])
    arData = {"Aritst Name":artArtistList,"Freq":artistFreqList}
    ar = pd.DataFrame(data=arData)
    ar.index = np.arange(1,len(ar)+1)

    #Album Chart
    albumData = lastfm_weeklyChart(timeList,'user.getWeeklyAlbumChart')
    totalAlbums = len(albumData['weeklyalbumchart']['album'])

    alAlbumList = []
    albumFreqList = []
    for i in range(0,totalAlbums):
        alAlbumList.append(albumData['weeklyalbumchart']['album'][i]['name'])
        albumFreqList.append(albumData['weeklyalbumchart']['album'][i]['playcount'])
    alData = {"Album Name":alAlbumList,"Freq":albumFreqList}
    al = pd.DataFrame(data=alData)
    al.index = np.arange(1,len(al)+1)
    #-------------------------------------------------------------------------------------
    totalTracksPlayed = 0
    for k,v in songDict.items():
        totalTracksPlayed += songDict[k]['PlayCount']
    #--------------------------------------------------------------------------------------
    #Picture Data
    
    def lastfm_trackGetInfo(artist,track):
        headers = {"user-agent": USER_AGENT}
        url = 'http://ws.audioscrobbler.com/2.0/'
        payload = {'method' : 'track.getInfo'}
        payload['user'] = USER_AGENT
        payload['api_key'] = API_KEY
        payload['format'] = 'json'
        payload["autocorrect"] = 1
        payload["artist"] = artist
        payload["track"] = track
        payload["username"] = USER_AGENT
        response = requests.get(url,headers=headers, params=payload)
        return response.json()
    def getpicUrl(num):
        data = lastfm_trackGetInfo(songDict[num]["Artist"],songDict[num]["Track"])
        picUrl = data["track"]['album']['image'][3]["#text"]
        return picUrl
    #User Image
    userImage = getUserData('picture')
    #Image 1
    count = 0
    try:
        image1 = getpicUrl(0)
    except KeyError:
        image1 = ""
    while len(image1) < 1 :
        try:
            image1 = getpicUrl(count+1)
            count += 1
        except KeyError:
            count += 1
        
    #Image 2
    try:
        image2 = getpicUrl(count+1)
        if image1 == image2: #Case for when album pic is the same
            image2 = ""
            count += 1
    except KeyError:
        image2 = ""
    while len(image2) < 1 :
        try:
            image2 = getpicUrl(count+1)
            count += 1
        except KeyError:
            count += 1
#-----------------------------------------------------------------------------------------------------------
    #Genre Feature
    def lastfm_artistGetTag(artist):
        headers = {"user-agent": USER_AGENT}
        url = 'http://ws.audioscrobbler.com/2.0/'
        payload = {'method' : 'artist.getTopTags'}
        payload['user'] = USER_AGENT
        payload['api_key'] = API_KEY
        payload['format'] = 'json'
        payload["autocorrect"] = 1
        payload["artist"] = artist
        response = requests.get(url,headers=headers, params=payload)
        return response.json()
    genreDic = {}
    genereCounter = 0
    for k,v in songDict.items():
        if genereCounter >= 50:
            break
        aData = lastfm_artistGetTag(songDict[k]["Artist"])
        genereCounter += 1
        for e in range(0,5):
            try:
                count = aData['toptags']['tag'][e]['count']
                tag = aData['toptags']['tag'][e]['name']
                if tag in genreDic:
                    genreDic[tag] += count
                else:
                    genreDic[tag] = count
            except IndexError:
                break
    def sortDictbyValue2(dictionary):
        sorted_keys = sorted(dictionary,reverse = True,key=lambda x: (dictionary[x]))
        tempDict = {}
        for i in sorted_keys:
            tempDict[i] = ""
        tempDict2 = {}
        for (k,v),(k2,v2) in zip(dictionary.items(),tempDict.items()):
            tempDict2[k2] = dictionary[k2]
        return tempDict2
    genreDic = sortDictbyValue2(genreDic)
    genreList = []
    genreCountList = []
    count = 0
    for k,v in genreDic.items():
        genreList.append(k)
        genreCountList.append(v)
        count += 1
        if count > 4:
            break
    genrePie = go.Figure(data=[go.Pie(labels=genreList,values=genreCountList)])
    #--------------------------------------------------------------------------------------
    with header:
        st.title(f"Welcome {USER_AGENT} to your Yearly Song Report")
        try:
            st.image(userImage)
            st.write(f"Profile picture of {USER_AGENT}")
        except FileNotFoundError:
            st.write("User has no profile picture")
        st.subheader("Created by <NAME>")
        st.write("Powered by AudioScrobbler from Last.FM")
        st.write("Last.FM URL: https://www.last.fm/")
    with yearlyData:
        st.header(f"Yearly Statistics for {USER_AGENT} in {year}")
        picol1,picol2 = st.beta_columns(2)
        picol1.image(image1)
        picol2.image(image2)
        st.dataframe(df)
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(ar)
        tabcol2.dataframe(al)
        st.subheader("Genre Pie Chart")
        st.write(genrePie)
        
    #--------------------------------------------------------------------------------------
    #Each Month Setup
    def getMonthUniTime(year,month):
        monthDayList = monthConvert(month,year)
        timeStart = float(time.mktime(datetime.datetime(year,monthDayList[0],1,0,0,0).timetuple())) + 28800  #For CT + 21600
        timeEnd = float(time.mktime(datetime.datetime(year,monthDayList[0],monthDayList[1],23,59,59).timetuple())) + 28800
            
        timeStart = format(timeStart, ".0f")
        timeEnd = format(timeEnd, ".0f")
        floatTime = [timeStart,timeEnd]
        return [str(floatTime) for floatTime in floatTime]
       
    def getMonthlyTables(year,month):
        timeList = getMonthUniTime(year,month)
        #Tracks
        trackData = lastfm_weeklyChart(timeList,'user.getWeeklyTrackChart')
            
        totalSongs = len(trackData['weeklytrackchart']['track'])
        songDict = {}
        for i in range(0,totalSongs):
            songDict[i] = {"Track":trackData['weeklytrackchart']['track'][i]['name'],"PlayCount":int(trackData['weeklytrackchart']['track'][i]['playcount'])
            ,"Artist":trackData['weeklytrackchart']['track'][i]['artist']['#text']}
        totalTracks = 0
        for i in range(0,totalSongs):
            totalTracks += songDict[i]["PlayCount"]
            
        SongList = []
        ArtistList = []
        SongFreqList = []
        for i in range(0,totalSongs):
            SongList.append(songDict[i]["Track"])
            ArtistList.append(songDict[i]["Artist"])
            SongFreqList.append(songDict[i]["PlayCount"])
        tData = {'Song Name' : SongList,'Artist':ArtistList,'PlayCount':SongFreqList}
        td = pd.DataFrame(data=tData)
        td.index = np.arange(1,len(td)+1)
        #Artists
        artistData = lastfm_weeklyChart(timeList,'user.getWeeklyArtistChart')
            
        totalArtists = len(artistData['weeklyartistchart']['artist'])
        artArtistList = []
        artistFreqList = []
        for i in range(0,totalArtists):
            artArtistList.append(artistData['weeklyartistchart']['artist'][i]['name'])
            artistFreqList.append(artistData['weeklyartistchart']['artist'][i]['playcount'])
        arData = {"Artist Name":artArtistList,"PlayCount":artistFreqList}
        ar = pd.DataFrame(data=arData)
        ar.index = np.arange(1,len(ar)+1)
        #Albums
        albumData = lastfm_weeklyChart(timeList,'user.getWeeklyAlbumChart')
        totalAlbums = len(albumData['weeklyalbumchart']['album'])

        alAlbumList = []
        albumFreqList = []
        for i in range(0,totalAlbums):
            alAlbumList.append(albumData['weeklyalbumchart']['album'][i]['name'])
            albumFreqList.append(albumData['weeklyalbumchart']['album'][i]['playcount'])
        alData = {"Album Name":alAlbumList,"Freq":albumFreqList}
        al = pd.DataFrame(data=alData)
        al.index = np.arange(1,len(al)+1)
        #Return 3 tables
        return [td,ar,al,tData,arData]
    def getTotalSongs(year,month):
        timeList = getMonthUniTime(year,month)
        #Tracks
        trackData = lastfm_weeklyChart(timeList,'user.getWeeklyTrackChart')
            
        totalSongs = len(trackData['weeklytrackchart']['track'])
        totalTracks = 0
        for i in range(0,totalSongs):
            totalTracks += int(trackData['weeklytrackchart']['track'][i]['playcount'])
        return totalTracks
    
    theMonths = ["January","February","March","April","May","June","July","August","September","October","November","December"]

    monthTables = []
    totalSongsList = []
    for month in theMonths:
        monthTables.append(getMonthlyTables(year,month))
        totalSongsList.append(getTotalSongs(year,month))
    ts = pd.DataFrame(data=totalSongsList,index=[1,2,3,4,5,6,7,8,9,10,11,12])
    
    janTables = monthTables[0]
    febTables = monthTables[1]
    marTables = monthTables[2]
    aprTables = monthTables[3]
    mayTables = monthTables[4]
    junTables = monthTables[5]
    julTables = monthTables[6]
    augTables = monthTables[7]
    sepTables = monthTables[8]
    octTables = monthTables[9]
    novTables = monthTables[10]
    decTables = monthTables[11]
    
    #-------------------------------------------------------------------------------------------------
    def getTopSong():
        Song = []
        Artist = []
        Plays = []
        for i in range(0,12):
            try:
                Song.append(monthTables[i][3]['Song Name'][0])
                Artist.append(monthTables[i][3]['Artist'][0])
                Plays.append(monthTables[i][3]['PlayCount'][0])
            except IndexError:
                Song.append("-")
                Artist.append("-")
                Plays.append(0)
        return [Song,Artist,Plays]
    def getTopArtist():
        Artist = []
        Plays = []
        for i in range(0,12):
            try:
                Artist.append(monthTables[i][4]['Artist Name'][0])
                Plays.append(monthTables[i][4]['PlayCount'][0])
            except IndexError:
                Artist.append("-")
                Plays.append(0)
        return [Artist,Plays]
    
    TopSongData = getTopSong()
    topData = {"Track":TopSongData[0],"Artist":TopSongData[1],"Freq":TopSongData[2]}
    tps = pd.DataFrame(data=topData,index=[1,2,3,4,5,6,7,8,9,10,11,12])
    
    tps2 = pd.DataFrame(data=TopSongData[2],index=[1,2,3,4,5,6,7,8,9,10,11,12])
    TopArtistData = getTopArtist()
    topAData = {"Artist":TopArtistData[0],"Freq":TopArtistData[1]}
    ta = pd.DataFrame(data=topAData,index=[1,2,3,4,5,6,7,8,9,10,11,12])
    #-------------------------------------------------------------------------------------------------
    #Displaying everything
    
    with topStuffData:
        st.subheader("Tracks played per month")
        st.bar_chart(ts)
        st.subheader("Top Songs from each Month")
        st.dataframe(tps)
        st.subheader("Top Artists from each Month")
        st.dataframe(ta)
        st.subheader("Top Songs Freq per month")
        st.bar_chart(tps2)
    with JanuaryData:
        st.header("January Data")
        st.dataframe(janTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(janTables[1])
        tabcol2.dataframe(janTables[2])
        st.write(f"Total songs played in month: {totalSongsList[0]}")
        
    with FebruaryData:
        st.header("February Data")
        st.dataframe(febTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(febTables[1])
        tabcol2.dataframe(febTables[2])
        st.write(f"Total songs played in month: {totalSongsList[1]}")
        
    with MarchData:
        st.header("March Data")
        st.dataframe(marTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(marTables[1])
        tabcol2.dataframe(marTables[2])
        st.write(f"Total songs played in month: {totalSongsList[2]}")
        
    with AprilData:
        st.header("April Data")
        st.dataframe(aprTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(aprTables[1])
        tabcol2.dataframe(aprTables[2])
        st.write(f"Total songs played in month: {totalSongsList[3]}")
    
    with MayData:
        st.header("May Data")
        st.dataframe(mayTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(mayTables[1])
        tabcol2.dataframe(mayTables[2])
        st.write(f"Total songs played in month: {totalSongsList[4]}")
        
    with JuneData:
        st.header("June Data")
        st.dataframe(junTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(junTables[1])
        tabcol2.dataframe(junTables[2])
        st.write(f"Total songs played in month: {totalSongsList[5]}")
        
    with JulyData:
        st.header("July Data")
        st.dataframe(julTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(julTables[1])
        tabcol2.dataframe(julTables[2])
        st.write(f"Total songs played in month: {totalSongsList[6]}")
        
    with AugustData:
        st.header("August Data")
        st.dataframe(augTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(augTables[1])
        tabcol2.dataframe(augTables[2])
        st.write(f"Total songs played in month: {totalSongsList[7]}")
        
    with SeptemberData:
        st.header("September Data")
        st.dataframe(sepTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(sepTables[1])
        tabcol2.dataframe(sepTables[2])
        st.write(f"Total songs played in month: {totalSongsList[8]}")
        
    with OctoberData:
        st.header("October Data")
        st.dataframe(octTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(octTables[1])
        tabcol2.dataframe(octTables[2])
        st.write(f"Total songs played in month: {totalSongsList[9]}")
        
    with NovemberData:
        st.header("November Data")
        st.dataframe(novTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(novTables[1])
        tabcol2.dataframe(novTables[2])
        st.write(f"Total songs played in month: {totalSongsList[10]}")
        
    with DecemberData:
        st.header("December Data")
        st.dataframe(decTables[0])
        tabcol1,tabcol2 = st.beta_columns(2)
        tabcol1.dataframe(decTables[1])
        tabcol2.dataframe(decTables[2])
        st.write(f"Total songs played in month: {totalSongsList[11]}")
    