# Bryan Schumaker (11/12/2010)

import libsaria
from libsaria import path
from libsaria.sources import library
from libsaria.sources import playlist
from libsaria import callbacks
import libsaria.xm as xml

add_child = xml.add_child
add_text  = xml.add_text
get_attrs = library.get_attrs
set_attr  = library.set_attr
file_id   = path.file_id
lib_file  = "library"
vers      = "%s.%s" % (libsaria.__major__, libsaria.__minor__)
if libsaria.__dev__ == True:
	lib_file = lib_file + "-dev"
lib_file += ".xml"
lib_file  = path.join(path.saria_dir(), lib_file)

xml_children = xml.children
xml_child    = xml.child
xml_attrs    = xml.attributes

#######################################
# Generic encode and decode functions #
#######################################

def decode_attr(attr):
	child = xml.child(attr)
	return (attr.nodeName, child.data.strip())

def encode_attr(doc, node, attr, value):
	child = add_child(doc, node, attr)
	add_text(doc, child, value)

def encode_track(doc, node, id):
	filepath, like, count = get_attrs(id, "filepath", "like", "count")
	if (like == None) and (count == 0):
		return
	child = add_child(doc, node, "track", {"like":like, "count":count})
	add_text(doc, child, filepath)

##################################
# xspf encode / decode functions #
##################################

def decode_xspf_track(location):
	file = xml.child(location).data.strip()
	if file[:7] == "file://":
		id = path.file_id(file[7:])
		if library.has_id(id):
			playlist.add_id(id)

def decode_xspf(child):
	tlist = xml.child(child)
	playlist.reset()
	for node in xml.children(tlist):
		try:
			loc = xml.get_elements(node, "location")[0]
			decode_xspf_track(loc)
		except:
			pass
	playlist.save()
	callbacks.load_playlist()

def encode_xspf(doc, node, id):
	filepath = get_attrs(id, "filepath")
	track    = add_child(doc, node, "track")
	location = add_child(doc, track, "location")
	add_text(doc, location, "file://%s" % filepath)

#########################
# v1.1 Decode functions #
#########################

def decode_track_v1_1(node):
	track = dict()
	for child in xml_children(node):
		key, value = decode_attr(child)
		track[key] = value
	id = file_id(track["filepath"])
	set_attr(id, "count", int(track["count"]))

def decode_v1_1(node):
	for track in xml_children(node):
		decode_track_v1_1(track)


#########################
# v1.2 Decode functions #
#########################

def decode_sources_v1_2(node):
	for child in xml_children(node):
		source = xml_child(child).data.strip()
		print "Scanning source: %s" % source
		libsaria.sources.new_source(source)

def decode_track_v1_2(node):
	for track in xml_children(node):
		attrs      = xml_attrs(track)
		name, path = decode_attr(track)
		id = file_id(path)
		set_attr(id, "count", int(attrs["count"]))

def decode_v1_2(node):
	children = xml_children(node)
	sources  = None
	tracks   = None
	for node in children:
		name = node.nodeName
		if name == "sources":
			sources = node
		elif name == "tracks":
			tracks = node
	decode_sources_v1_2(sources)
	decode_track_v1_2(tracks)


#########################
# v1.3 Decode functions #
#########################

def decode_track_v1_3(node):
	for track in xml_children(node):
		attrs      = xml_attrs(track)
		name, path = decode_attr(track)
		id = file_id(path)
		like = attrs["like"]
		if like == "True":
			like = True
		elif like == "False":
			like = False
		elif like == "None":
			like = None

		set_attr(id, "count", int(attrs["count"]))
		set_attr(id, "like", like)

def decode_v1_3(node):
	children = xml_children(node)
	sources  = None
	tracks   = None
	for node in children:
		name = node.nodeName
		if name == "sources":
			sources = node
		elif name == "tracks":
			tracks = node
	decode_sources_v1_2(sources)
	decode_track_v1_3(tracks)


#############################################
# Control will enter the export module here #
#############################################

def export():
	doc     = xml.new()
	child   = add_child(doc, doc, "library", {"version":vers})
	sources = add_child(doc, child, "sources")
	tracks  = add_child(doc, child, "tracks")
	for path in library.get_locations():
		encode_attr(doc, sources, "source", path)

	for id in library.walk():
		encode_track(doc, tracks, id)

	fout = open(lib_file, 'w')
	fout.write(doc.toprettyxml())
	fout.close()
	print "Wrote library to: %s" % lib_file

def save_playlist(filepath):
	file, ext = path.splitext(filepath)
	if ext != ".xml":
		filepath+=".xml"

	doc   = xml.new()
	child = add_child(doc, doc, "playlist", {"version":1, "xmlns":"http://xspf.org/ns/0/"})
	tlist = add_child(doc, child, "trackList")

	for id in playlist.walk():
		encode_xspf(doc, tlist, id)

	fout = open(filepath, 'w')
	fout.write(doc.toprettyxml())
	fout.close()
	print "Wrote playlist to: %s" % filepath

def import_xml(file):
	fin   = open(file)
	doc   = xml.parse(fin)
	child = xml.child(doc)
	if child.nodeName == "playlist":
		decode_xspf(child)
	elif child.nodeName == "library":
		import_library(child)

def import_library(child):
	attrs = xml.attributes(child)
	version = float(attrs.get("version", "1.1"))
	print "Decoding library version: %s" % version
	if version == 1.1:
		decode_v1_1(child)
	elif version == 1.2:
		decode_v1_2(child)
	elif version >= 1.3:
		decode_v1_3(child)
