from htmlgenerators import *
import database
from utilities import getArtistImage, getTrackImage
from malojatime import *
from urihandler import compose_querystring, internal_to_uri, uri_to_internal
import urllib
import datetime
import math


#def getpictures(ls,result,tracks=False):
#	from utilities import getArtistsInfo, getTracksInfo
#	if tracks:
#		for element in getTracksInfo(ls):
#			result.append(element.get("image"))
#	else:
#		for element in getArtistsInfo(ls):
#			result.append(element.get("image"))


#max_ indicates that no pagination should occur (because this is not the primary module)
def module_scrobblelist(page=0,perpage=100,max_=None,pictures=False,shortTimeDesc=False,earlystop=False,**kwargs):

	kwargs_filter = pickKeys(kwargs,"artist","track","associated")
	kwargs_time = pickKeys(kwargs,"timerange","since","to","within")

	if max_ is not None: perpage,page=max_,0

	firstindex = page * perpage
	lastindex = firstindex + perpage

	# if earlystop, we don't care about the actual amount and only request as many from the db
	# without, we request everything and filter on site
	maxkey = {"max_":lastindex} if earlystop else {}
	scrobbles = database.get_scrobbles(**kwargs_time,**kwargs_filter,**maxkey)
	if pictures:
		scrobbleswithpictures = [""] * firstindex + scrobbles[firstindex:lastindex]
		#scrobbleimages = [e.get("image") for e in getTracksInfo(scrobbleswithpictures)] #will still work with scrobble objects as they are a technically a subset of track objects
		#scrobbleimages = ["/image?title=" + urllib.parse.quote(t["title"]) + "&" + "&".join(["artist=" + urllib.parse.quote(a) for a in t["artists"]])  for t in scrobbleswithpictures]
		scrobbleimages = [getTrackImage(t["artists"],t["title"],fast=True) for t in scrobbleswithpictures]

	pages = math.ceil(len(scrobbles) / perpage)

	representative = scrobbles[0] if len(scrobbles) is not 0 else None

	# build list
	i = 0
	html = "<table class='list'>"
	for s in scrobbles:
		if i<firstindex:
			i += 1
			continue

		html += "<tr>"
		html += "<td class='time'>" + timestamp_desc(s["time"],short=shortTimeDesc) + "</td>"
		if pictures:
			img = scrobbleimages[i]
		else: img = None
		html += entity_column(s,image=img)
		html += "</tr>"

		i += 1
		if i>=lastindex:
			break


	html += "</table>"

	if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)

	return (html,len(scrobbles),representative)


def module_pulse(page=0,perpage=100,max_=None,**kwargs):

	from doreah.timing import clock, clockp

	kwargs_filter = pickKeys(kwargs,"artist","track","associated")
	kwargs_time = pickKeys(kwargs,"since","to","within","timerange","step","stepn","trail")

	if max_ is not None: perpage,page=max_,0

	firstindex = page * perpage
	lastindex = firstindex + perpage


	ranges = database.get_pulse(**kwargs_time,**kwargs_filter)

	pages = math.ceil(len(ranges) / perpage)

	ranges = ranges[firstindex:lastindex]

	# if time range not explicitly specified, only show from first appearance
#	if "since" not in kwargs:
#		while ranges[0]["scrobbles"] == 0:
#			del ranges[0]

	maxbar = max([t["scrobbles"] for t in ranges])
	maxbar = max(maxbar,1)

	#build list
	html = "<table class='list'>"
	for t in ranges:
		range = t["range"]
		html += "<tr>"
		html += "<td>" + range.desc() + "</td>"
		html += "<td class='amount'>" + scrobblesLink(range.urikeys(),amount=t["scrobbles"],**kwargs_filter) + "</td>"
		html += "<td class='bar'>" + scrobblesLink(range.urikeys(),percent=t["scrobbles"]*100/maxbar,**kwargs_filter) + "</td>"
		html += "</tr>"
	html += "</table>"

	if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)

	return html



def module_performance(page=0,perpage=100,max_=None,**kwargs):

	kwargs_filter = pickKeys(kwargs,"artist","track")
	kwargs_time = pickKeys(kwargs,"since","to","within","timerange","step","stepn","trail")

	if max_ is not None: perpage,page=max_,0

	firstindex = page * perpage
	lastindex = firstindex + perpage

	ranges = database.get_performance(**kwargs_time,**kwargs_filter)

	pages = math.ceil(len(ranges) / perpage)

	ranges = ranges[firstindex:lastindex]

	# if time range not explicitly specified, only show from first appearance
#	if "since" not in kwargs:
#		while ranges[0]["scrobbles"] == 0:
#			del ranges[0]


	minrank = 80
	for t in ranges:
		if t["rank"] is not None and t["rank"]+20 > minrank: minrank = t["rank"]+20

	#build list
	html = "<table class='list'>"
	for t in ranges:
		range = t["range"]
		html += "<tr>"
		html += "<td>" + range.desc() + "</td>"
		html += "<td class='rank'>" + ("#" + str(t["rank"]) if t["rank"] is not None else "No scrobbles") + "</td>"
		prct = (minrank+1-t["rank"])*100/minrank if t["rank"] is not None else 0
		html += "<td class='chart'>" + rankLink(range.urikeys(),percent=prct,**kwargs_filter,medal=t["rank"]) + "</td>"
		html += "</tr>"
	html += "</table>"

	if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)

	return html



def module_trackcharts(page=0,perpage=100,max_=None,**kwargs):

	kwargs_filter = pickKeys(kwargs,"artist","associated")
	kwargs_time = pickKeys(kwargs,"timerange","since","to","within")

	if max_ is not None: perpage,page=max_,0

	firstindex = page * perpage
	lastindex = firstindex + perpage

	tracks = database.get_charts_tracks(**kwargs_filter,**kwargs_time)

	pages = math.ceil(len(tracks) / perpage)

	# last time range (to compare)
	try:
		trackslast = database.get_charts_tracks(**kwargs_filter,timerange=kwargs_time["timerange"].next(step=-1))
		# create rank association
		lastrank = {}
		for tl in trackslast:
			lastrank[(*tl["track"]["artists"],tl["track"]["title"])] = tl["rank"]
		for t in tracks:
			try:
				t["delta"] = lastrank[(*t["track"]["artists"],t["track"]["title"])] - t["rank"]
			except:
				t["delta"] = math.inf
	except:
		pass

	if tracks != []:
		maxbar = tracks[0]["scrobbles"]
		representative = tracks[0]["track"]
	else:
		representative = None


	i = 0
	html = "<table class='list'>"
	for e in tracks:
		if i<firstindex:
			i += 1
			continue
		i += 1
		if i>lastindex:
			break
		html += "<tr>"
		# rank
		if i == firstindex+1 or e["scrobbles"] < prev["scrobbles"]:
			html += "<td class='rank'>#" + str(e["rank"]) + "</td>"
		else:
			html += "<td class='rank'></td>"
		# rank change
		if e.get("delta") is None:
			pass
		elif e["delta"] is math.inf:
			html += "<td class='rankup' title='New'>🆕</td>"
		elif e["delta"] > 0:
			html += "<td class='rankup' title='up from #" + str(e["rank"]+e["delta"]) + "'>↗</td>"
		elif e["delta"] < 0:
			html += "<td class='rankdown' title='down from #" + str(e["rank"]+e["delta"]) + "'>↘</td>"
		else:
			html += "<td class='ranksame' title='Unchanged'>âž¡</td>"
		# track
		html += entity_column(e["track"])
		# scrobbles
		html += "<td class='amount'>" + scrobblesTrackLink(e["track"],internal_to_uri(kwargs_time),amount=e["scrobbles"]) + "</td>"
		html += "<td class='bar'>" + scrobblesTrackLink(e["track"],internal_to_uri(kwargs_time),percent=e["scrobbles"]*100/maxbar) + "</td>"
		html += "</tr>"
		prev = e
	html += "</table>"

	if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)

	return (html,representative)


def module_artistcharts(page=0,perpage=100,max_=None,**kwargs):

	kwargs_filter = pickKeys(kwargs,"associated") #not used right now
	kwargs_time = pickKeys(kwargs,"timerange","since","to","within")

	if max_ is not None: perpage,page=max_,0

	firstindex = page * perpage
	lastindex = firstindex + perpage

	artists = database.get_charts_artists(**kwargs_filter,**kwargs_time)

	pages = math.ceil(len(artists) / perpage)


	# last time range (to compare)
	try:
	#from malojatime import _get_next
		artistslast = database.get_charts_artists(**kwargs_filter,timerange=kwargs_time["timerange"].next(step=-1))
		# create rank association
		lastrank = {}
		for al in artistslast:
			lastrank[al["artist"]] = al["rank"]
		for a in artists:
			try:
				a["delta"] = lastrank[a["artist"]] - a["rank"]
			except:
				a["delta"] = math.inf
	except:
		pass

	if artists != []:
		maxbar = artists[0]["scrobbles"]
		representative = artists[0]["artist"]
	else:
		representative = None

	i = 0
	html = "<table class='list'>"
	for e in artists:
		if i<firstindex:
			i += 1
			continue
		i += 1
		if i>lastindex:
			break
		html += "<tr>"
		# rank
		if i == firstindex+1 or e["scrobbles"] < prev["scrobbles"]:
			html += "<td class='rank'>#" + str(e["rank"]) + "</td>"
		else:
			html += "<td class='rank'></td>"
		# rank change
		#if "within" not in kwargs_time: pass
		if e.get("delta") is None:
			pass
		elif e["delta"] is math.inf:
			html += "<td class='rankup' title='New'>🆕</td>"
		elif e["delta"] > 0:
			html += "<td class='rankup' title='up from #" + str(e["rank"]+e["delta"]) + "'>↗</td>"
		elif e["delta"] < 0:
			html += "<td class='rankdown' title='down from #" + str(e["rank"]+e["delta"]) + "'>↘</td>"
		else:
			html += "<td class='ranksame' title='Unchanged'>âž¡</td>"
		# artist
		html += entity_column(e["artist"],counting=e["counting"])
		# scrobbles
		html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],internal_to_uri(kwargs_time),amount=e["scrobbles"],associated=True) + "</td>"
		html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],internal_to_uri(kwargs_time),percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
		html += "</tr>"
		prev = e

	html += "</table>"

	if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)

	return (html, representative)



def module_toptracks(pictures=True,**kwargs):

	kwargs_filter = pickKeys(kwargs,"artist","associated")
	kwargs_time = pickKeys(kwargs,"timerange","since","to","within","step","stepn","trail")

	tracks = database.get_top_tracks(**kwargs_filter,**kwargs_time)

	if tracks != []:
		maxbar = max(t["scrobbles"] for t in tracks)


		# track with most #1 positions
		max_appear = 0
		representatives = list(t["track"] for t in tracks if t["track"] is not None)
		for t in representatives:
			max_appear = max(max_appear,representatives.count(t))
		#representatives.sort(key=lambda reftrack:len([t for t in tracks if t["track"] == reftrack["track"] and t["track"] is not None]))
		representatives = [t for t in tracks if representatives.count(t["track"]) == max_appear]
		# of these, track with highest scrobbles in its #1 range
		representatives.sort(key=lambda t: t["scrobbles"])
		representative = representatives[-1]["track"]
	else:
		representative = None


	i = 0
	html = "<table class='list'>"
	for e in tracks:

		#fromstr = "/".join([str(p) for p in e["from"]])
		#tostr = "/".join([str(p) for p in e["to"]])
		range = e["range"]

		i += 1
		html += "<tr>"


		html += "<td>" + range.desc() + "</td>"
		if e["track"] is None:
			if pictures:
				html += "<td><div></div></td>"
			html += "<td class='stats'>" + "No scrobbles" + "</td>"
			#html += "<td>" + "" + "</td>"
			html += "<td class='amount'>" + "0" + "</td>"
			html += "<td class='bar'>" + "" + "</td>"
		else:
			if pictures:
				img = getTrackImage(e["track"]["artists"],e["track"]["title"],fast=True)
			else: img = None
			html += entity_column(e["track"],image=img)
			html += "<td class='amount'>" + scrobblesTrackLink(e["track"],range.urikeys(),amount=e["scrobbles"]) + "</td>"
			html += "<td class='bar'>" + scrobblesTrackLink(e["track"],range.urikeys(),percent=e["scrobbles"]*100/maxbar) + "</td>"
		html += "</tr>"
		prev = e
	html += "</table>"

	return (html,representative)

def module_topartists(pictures=True,**kwargs):

	kwargs_time = pickKeys(kwargs,"timerange","since","to","within","step","stepn","trail")

	artists = database.get_top_artists(**kwargs_time)

	if artists != []:
		maxbar = max(a["scrobbles"] for a in artists)

		# artists with most #1 positions
		max_appear = 0
		representatives = list(a["artist"] for a in artists if a["artist"] is not None)
		for a in representatives:
			max_appear = max(max_appear,representatives.count(a))
		representatives = [a for a in artists if representatives.count(a["artist"]) == max_appear]
		# of these, artist with highest scrobbles in their #1 range
		representatives.sort(key=lambda a: a["scrobbles"])

		representative = representatives[-1]["artist"]
	else:
		representative = None


	i = 0
	html = "<table class='list'>"
	for e in artists:

		#fromstr = "/".join([str(p) for p in e["from"]])
		#tostr = "/".join([str(p) for p in e["to"]])
		range = e["range"]

		i += 1
		html += "<tr>"


		html += "<td>" + range.desc() + "</td>"

		if e["artist"] is None:
			if pictures:
				html += "<td><div></div></td>"
			html += "<td class='stats'>" + "No scrobbles" + "</td>"
			html += "<td class='amount'>" + "0" + "</td>"
			html += "<td class='bar'>" + "" + "</td>"
		else:
			if pictures:
				img = getArtistImage(e["artist"],fast=True)
			else: img = None
			html += entity_column(e["artist"],image=img)
			html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],range.urikeys(),amount=e["scrobbles"],associated=True) + "</td>"
			html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],range.urikeys(),percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
		html += "</tr>"
		prev = e
	html += "</table>"

	return (html,representative)


def module_artistcharts_tiles(**kwargs):

	kwargs_filter = pickKeys(kwargs,"associated") #not used right now
	kwargs_time = pickKeys(kwargs,"timerange","since","to","within")

	artists = database.get_charts_artists(**kwargs_filter,**kwargs_time)[:14]
	while len(artists)<14: artists.append(None)

	i = 1

	bigpart = [0,1,2,6,15]
	smallpart = [0,1,2,4,6,9,12,15]
	#rnk = (0,0) #temporary store so entries with the same scrobble amount get the same rank

	html = """<table class="tiles_top"><tr>"""

	for e in artists:


		if i in bigpart:
			n = bigpart.index(i)
			html += """<td><table class="tiles_""" + str(n) + """x""" + str(n) + """ tiles_sub">"""

		if i in smallpart:
			html += "<tr>"


		if e is not None:
			html += "<td onclick='window.location.href=\"" \
				+ link_address(e["artist"]) \
				+ "\"' style='cursor:pointer;background-image:url(\"" + getArtistImage(e["artist"],fast=True) + "\");'>" \
				+ "<span class='stats'>" + "#" + str(e["rank"]) + "</span> <span>" + html_link(e["artist"]) + "</span></td>"
		else:
			html += "<td><span class='stats'></span> <span></span></td>"

		i += 1

		if i in smallpart:
			html += "</tr>"

		if i in bigpart:
			html += "</table></td>"

	html += """</tr></table>"""

	return html


def module_trackcharts_tiles(**kwargs):

	kwargs_filter = pickKeys(kwargs,"artist","associated")
	kwargs_time = pickKeys(kwargs,"timerange","since","to","within")

	tracks = database.get_charts_tracks(**kwargs_filter,**kwargs_time)[:14]
	while len(tracks)<14: tracks.append(None) #{"track":{"title":"","artists":[]}}

	i = 1

	bigpart = [0,1,2,6,15]
	smallpart = [0,1,2,4,6,9,12,15]
	#rnk = (0,0) #temporary store so entries with the same scrobble amount get the same rank


	html = """<table class="tiles_top"><tr>"""

	for e in tracks:


		if i in bigpart:
			n = bigpart.index(i)
			html += """<td><table class="tiles_""" + str(n) + """x""" + str(n) + """ tiles_sub">"""

		if i in smallpart:
			html += "<tr>"


		if e is not None:
			html += "<td onclick='window.location.href=\"" \
				+ link_address(e["track"]) \
				+ "\"' style='cursor:pointer;background-image:url(\"" + getTrackImage(e["track"]["artists"],e["track"]["title"],fast=True) + "\");'>" \
				+ "<span class='stats'>" + "#" + str(e["rank"]) + "</span> <span>" + html_link(e["track"]) + "</span></td>"
		else:
			html += "<td><span class='stats'></span> <span></span></td>"

		i += 1

		if i in smallpart:
			html += "</tr>"

		if i in bigpart:
			html += "</table></td>"

	html += """</tr></table>"""

	return html



def module_paginate(page,pages,perpage,**keys):

	unchangedkeys = internal_to_uri({**keys,"perpage":perpage})

	html = "<div class='paginate'>"

	if page > 1:
		html += "<a href='?" + compose_querystring(unchangedkeys,internal_to_uri({"page":0})) + "'><span class='stat_selector'>" + "1" + "</span></a>"
		html += " | "

	if page > 2:
		html += " ... | "

	if page > 0:
		html += "<a href='?" + compose_querystring(unchangedkeys,internal_to_uri({"page":page-1})) + "'><span class='stat_selector'>" + str(page) + "</span></a>"
		html += " « "

	html += "<span style='opacity:0.5;' class='stat_selector'>" + str(page+1) + "</span>"

	if page < pages-1:
		html += " » "
		html += "<a href='?" + compose_querystring(unchangedkeys,internal_to_uri({"page":page+1})) + "'><span class='stat_selector'>" + str(page+2) + "</span></a>"

	if page < pages-3:
		html += " | ... "

	if page < pages-2:
		html += " | "
		html += "<a href='?" + compose_querystring(unchangedkeys,internal_to_uri({"page":pages-1})) + "'><span class='stat_selector'>" + str(pages) + "</span></a>"


	html += "</div>"

	return html



# THIS FUNCTION USES THE ORIGINAL URI KEYS!!!
def module_filterselection(keys,time=True,delimit=False):

	from malojatime import today, thisweek, thismonth, thisyear, alltime

	filterkeys, timekeys, delimitkeys, extrakeys = uri_to_internal(keys)
	# drop keys that are not relevant so they don't clutter the URI
	if not time: timekeys = {}
	if not delimit: delimitkeys = {}
	if "page" in extrakeys: del extrakeys["page"]
	internalkeys = {**filterkeys,**timekeys,**delimitkeys,**extrakeys}

	html = ""


	if time:

		# wonky selector for precise date range

#		fromdate = start_of_scrobbling()
#		todate = end_of_scrobbling()
#		if keys.get("since") is not None: fromdate = keys.get("since")
#		if keys.get("to") is not None: todate = keys.get("to")
#		if keys.get("in") is not None: fromdate, todate = keys.get("in"), keys.get("in")
#		fromdate = time_fix(fromdate)
#		todate = time_fix(todate)
#		fromdate, todate = time_pad(fromdate,todate,full=True)
#		fromdate = [str(e) if e>9 else "0" + str(e) for e in fromdate]
#		todate = [str(e) if e>9 else "0" + str(e) for e in todate]
#
#		html += "<div>"
#		html += "from <input id='dateselect_from' onchange='datechange()' type='date' value='" + "-".join(fromdate) + "'/> "
#		html += "to <input id='dateselect_to' onchange='datechange()' type='date' value='" + "-".join(todate) + "'/>"
#		html += "</div>"

		# relative to current range
		html += "<div>"

		thisrange = timekeys.get("timerange")
		prevrange = thisrange.next(-1)
		nextrange = thisrange.next(1)

		if prevrange is not None:
			link = compose_querystring(internal_to_uri({**internalkeys,"timerange":prevrange}))
			html += "<a href='?" + link + "'><span class='stat_selector'>" + prevrange.desc() + "</span></a>"
			html += " « "
		if prevrange is not None or nextrange is not None:
			html += "<span class='stat_selector' style='opacity:0.5;'>" + thisrange.desc() + "</span>"
		if nextrange is not None:
			html += " » "
			link = compose_querystring(internal_to_uri({**internalkeys,"timerange":nextrange}))
			html += "<a href='?" + link + "'><span class='stat_selector'>" + nextrange.desc() + "</span></a>"

		html += "</div>"




	categories = [
		{
			"active":time,
			"options":{
				"Today":{"timerange":today()},
				"This Week":{"timerange":thisweek()},
				"This Month":{"timerange":thismonth()},
				"This Year":{"timerange":thisyear()},
				"All Time":{"timerange":alltime()}
			}
		},
		{
			"active":delimit,
			"options":{
				"Daily":{"step":"day","stepn":1},
				"Weekly":{"step":"week","stepn":1},
				"Fortnightly":{"step":"week","stepn":2},
				"Monthly":{"step":"month","stepn":1},
				"Quarterly":{"step":"month","stepn":3},
				"Yearly":{"step":"year","stepn":1}
			}
		},
		{
			"active":delimit,
			"options":{
				"Standard":{"trail":1},
				"Trailing":{"trail":2},
				"Long Trailing":{"trail":3},
				"Inert":{"trail":10},
				"Cumulative":{"trail":math.inf}
			}
		}

	]

	for c in categories:

		if c["active"]:

			optionlist = []
			for option in c["options"]:
				values = c["options"][option]
				link = "?" + compose_querystring(internal_to_uri({**internalkeys,**values}))

				if all(internalkeys.get(k) == values[k] for k in values):
					optionlist.append("<span class='stat_selector' style='opacity:0.5;'>" + option + "</span>")
				else:
					optionlist.append("<a href='" + link + "'><span class='stat_selector'>" + option + "</span></a>")

			html += "<div>" + " | ".join(optionlist) + "</div>"

	return html