#!/usr/bin/python

import os
import sys
import fileinput
import re
import sha
import base64
import subprocess
import musicbrainz2.webservice as ws
import musicbrainz2
import logging
import glob
import urllib2
import MusicBrainzHelper

##########################################################################
## flac helper code                                                     ##
##########################################################################
class FlacHelper():
	def __init__(self, filename):
		self.filename = filename

	# run metaflac and return the output as an array of strings
	def metaflac(self, args):
		for i in range(0, len(args)):
			if (type(args[i]) == str):
				args[i] = args[i].decode('cp1252')
			if (type(args[i]) == unicode):
				args[i] = args[i].encode('cp1252')
		commandline = subprocess.list2cmdline(args)
		mflac = subprocess.Popen(args, shell=False, executable="d:/util/bin/metaflac.exe", bufsize=1024, stdout=subprocess.PIPE).stdout
		output = mflac.readlines()
		mflac.close()
		# removing trailing newlines
		output = [ line.decode('cp437') for line in output ]
		output = [ line.rstrip("\r\n") for line in output ]
		return output

	# get the flac cuesheet from a flac file
	def readFlacCuesheet(self):
		args = [ 'metaflac.exe', '--export-cuesheet-to=-', self.filename ]
		return self.metaflac(args)

	# get the EAC cuesheet from a flac file.  This is expected to live under
	# a tag called "cuesheet"
	def readEacCuesheet(self):
		args = [ 'metaflac.exe', '--show-tag=cuesheet', self.filename ]
		return self.metaflac(args)

	def getMusicBrainzId(self):
		args = [ 'metaflac.exe', '--show-tag=DISC_MUSICBRAINZ_ID', self.filename ]
		mbid = self.metaflac(args)
		if len(mbid) > 0:
			return mbid[0].partition("=")[2]
		else:
			return None

	def setMusicBrainzId(self, id):
		args = [ 'metaflac.exe', '--remove-tag=DISC_MUSICBRAINZ_ID', self.filename ]
		self.metaflac(args)
		args = [ 'metaflac.exe', '--set-tag=DISC_MUSICBRAINZ_ID=' + id, self.filename ]
		self.metaflac(args)

	# get the artist and title from our flac file
	def getArtistAndTitle(self):
		cuesheet = self.readEacCuesheet()
		artist = ''
		title = ''

		artistRegex = re.compile(r'^PERFORMER "(?P<performer>[^"]*)')
		titleRegex = re.compile(r'^TITLE "(?P<title>[^"]*)')
		
		for line in cuesheet:
			artistMatch = artistRegex.search(line)
			if artistMatch:
				artist = artistMatch.group('performer')
				continue

			titleMatch = titleRegex.search(line)
			if titleMatch:
				title = titleMatch.group('title')
				continue

		if artist == '' and title == '':
			# this could be an matt-style flac with no EAC cuesheet
			args = [ 'metaflac.exe', '--show-tag=DISC_PERFORMER', self.filename ]
			artist = self.metaflac(args)
			args = [ 'metaflac.exe', '--show-tag=DISC_TITLE', self.filename ]
			title = self.metaflac(args)
			artist = artist[0].partition("=")[2]
			title = title[0].partition("=")[2]

		return [ artist, title ]

	# generate a musicbrainz DiscId from a flac cuesheet
	def getDiscIdAndTrackCount(self):
		cuesheet = self.readFlacCuesheet()

		FRAMES_PER_SECOND = 75
		SAMPLES_PER_SECOND = 44100
		SAMPLES_PER_FRAME = SAMPLES_PER_SECOND // FRAMES_PER_SECOND

		pregap = 0
		currentTrackFrame = 0
		pregapRegex = re.compile(r'PREGAP (?P<min>\d+):(?P<sec>\d\d):(?P<frame>\d\d)')
		startTrackRegex = re.compile(r'INDEX 01 (?P<min>\d+):(?P<sec>\d\d):(?P<frame>\d\d)')
		leadInRegex = re.compile(r'REM FLAC__lead-in (?P<sample>\d+)')
		leadOutRegex = re.compile(r'REM FLAC__lead-out 170 (?P<sample>\d+)')
		raw_framelist = list()

		numTracks = 0

		for line in cuesheet:
			pregapMatch = pregapRegex.search(line)
			if pregapMatch:
				pregap = (int((pregapMatch.group('min')) * 60) + int(pregapMatch.group('sec'))) * FRAMES_PER_SECOND + int(pregapMatch.group('frame'))
				continue

			startTrackMatch = startTrackRegex.search(line)
			if startTrackMatch:
				numTracks += 1
				currentTrackFrame = ((int(startTrackMatch.group('min')) * 60) + int(startTrackMatch.group('sec'))) * FRAMES_PER_SECOND + int(startTrackMatch.group('frame'))
				raw_framelist.append(currentTrackFrame)
				continue

			leadInMatch = leadInRegex.search(line)
			if leadInMatch:
				leadInFrame = long(leadInMatch.group('sample')) // SAMPLES_PER_FRAME
				continue

			leadOutMatch = leadOutRegex.search(line)
			if leadOutMatch:
				leadOutFrame_raw = long(leadOutMatch.group('sample')) // SAMPLES_PER_FRAME
				continue

		leadOutFrame = leadOutFrame_raw + leadInFrame

		framelist = [i + leadInFrame + pregap for i in raw_framelist]

		secondslist = [i//FRAMES_PER_SECOND for i in framelist]

		discIdLongForm = ""
		discIdLongForm = discIdLongForm + "%02X" % 1
		discIdLongForm = discIdLongForm + "%02X" % numTracks
		discIdLongForm = discIdLongForm + "%08X" % leadOutFrame
		for x in framelist:
				discIdLongForm = discIdLongForm + "%08X" % x
		for x in range(numTracks, 99):
				discIdLongForm = discIdLongForm + "%08X" % 0
		discid = base64.standard_b64encode(sha.new(discIdLongForm).digest())
		discid = discid.replace("+", ".")
		discid = discid.replace("/", "_")
		discid = discid.replace("=", "-")

		return [ discid, numTracks ]

