from distutils.log import debug
import os, sys

import random
import datetime
import glob
# from xml.dom.minidom import Document
import markov
import pickle
import subprocess
import gradio as gr
import time
from MC.markov_chain import get_pngs




#TODO: convert these into inputs
# lengthofsong = 10 Should we control this? Setting it to random now
timesignature = ['3/4','4/4','1/8','6/8','2/4'] #Sometimes the letter ā€œCā€ (meaning common time) will be used in place of 4/4. 
#Both C and 4/4 indicate that there are four quarter note beats in each measure.
keysignature = ["C","G","D","No selection"]
difficulty = ["beginner","intermediate","expert"]
key_enforced = False
key_enforced = True #Set to true if user wants in specific key

# get the list of filenames (abc files downloaded from http://www.norbeck.nu/abc/)
# getdirs = []
# dirs = ["hn201612/i/*.abc", "hn201612/s/*.abc"]
# dirs = ["data/*.abc"]
# dirs = ["data"]
# for dir1 in dirs:
# 	for filename in glob.iglob(dir1):
# 		getdirs += [filename]

selected_timeSign = '3/4' #Default values
selected_keySign = 'C' #Default Values
deployed = True


GlobalUIGallery = False
#Finds all absolute paths in directory
#https://stackoverflow.com/questions/9816816/get-absolute-paths-of-all-files-in-a-directory
def abs_paths(dir):
    for dir_path,_,filenames in os.walk(dir):
        for f in filenames:
            yield os.path.abspath(os.path.join(dir_path, f))

def time_sigFinder(time_Signature):
	if time_Signature == "4/4":
		return 'M:4/4',4
	elif time_Signature == "3/4":
		return 'M:3/4',3
	elif time_Signature == "2/4":
		return 'M:2/4',2
	elif time_Signature == "1/8":
		pass
	elif time_Signature == "2/4":
		return 'M:2/4',2
	elif time_Signature == "2/2":
		return 'M:2/2',2
# def get_pngs(path):
# 	filelist=os.listdir(path)
# 	for fichier in filelist[:]: # filelist[:] makes a copy of filelist.
# 		if not(fichier.endswith(".png")):
# 			filelist.remove(fichier)
# 	newlist = [path+'/'+x for x in filelist] #making it cwd
# 	return newlist
def music_gen(difficulty,time_Signature, Key_Signature):
	if deployed:
		#delete all files stored in gen_songs_abc
		command = "rm -r gen_songs_abc/*"
		subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
		
	corpus = []
	song = []
	selected_timeSign = time_Signature
	selected_keySign = Key_Signature
	data_path = "data/"+str(difficulty)
# ex_filename = "hn201612/i/hnsong1.abc"
# parsing on file to extract songs and add them to corpus
	for filename in abs_paths(data_path):
		with open(filename) as f:
			lines = f.readlines()
			last = len(lines)
			accepted = False
			for index, line in enumerate(lines):
				if (line.find("|") < 0 and index - 1 == last):
					# if the next line does not have pipes add song to corpus and then set song variable empty again
					if accepted and key_enforced and key_accepted:
						corpus.append(song)
						accepted = False
						key_accepted = False
					if accepted:
						corpus.append(song)
						accepted = False
					song = []
				else:
					if line.find("|") > -1:
						# a line should be split on "|" and copied to the corpus if it has pipes
						sline = line.split("|")
						# add the list of measures to the song
						song += [x.strip("\r\n") for x in sline if len(x.strip("\r\n")) > 0]
						last = index
					elif "M:" in line:
						#time signature
						if selected_timeSign == "4/4":
							if "4/4" in line or "C|" in line:
								accepted = True
						elif selected_timeSign in line:
							accepted = True
					elif line.find("K:") and key_enforced:
						#key signature
						if selected_keySign in line:
							key_accepted = True
						
	# print("Training on {} songs...".format(len(corpus)))

	# MARKOV PART
	# n-gram length for markov model
	n = 1

	model = markov.generate_model_from_token_lists(corpus, n)


	# save pickle
	# with open('markov_chain.pickle', 'wb') as handle:
	# 	pickle.dump(model, handle)


	def nextword(word):
		return markov.generate(model, 3, seed=word, max_iterations=1)


	def writesong(songlength, first):
		song = [first]
		for i in range(songlength):
			song += nextword(str(song[-1]))
		return song

	# choose a random song length from list of song lengths in corpus
	lengthofsong = random.choice([len(x) for x in corpus if len(x) > 10])
	song_len = [len(x) for x in corpus if len(x)>10]
	song_len.sort()
	firstnote = markov.generate(model, n, max_iterations=3)[0]
	# print "first note: {}".format(firstnote)

	print("Here is the song in abc format:")
	song = writesong(lengthofsong, firstnote)
	dob = datetime.datetime.now().strftime('%H%M%S')

	modifier = format(dob)
	path = "gen_songs_abc/song_"+modifier
	# make song file
	# songname = "./gen_songs_abc/gen_song_{}.abc".modifier
	song_path = path+"/gen_song_"+modifier #without extension
	songname = path+"/gen_song_"+modifier+".abc"

	print("\n\nYou can find the song in {}".format(songname))
	lastpart = lengthofsong - lengthofsong%4

	# hack to include dictionary at the beginning of every abc file
	# will add a more sophisticated way to generate the values in the future
	title = "Markov Song {}".format(dob)
	final_timeS,numOfnotes = time_sigFinder(time_Signature)
	songbeginning = ['X:1','T:' + title, 'R:song', 'C:Visakh Ajith', 'Z:id:hn-song-111', final_timeS, 'L:1/8', 'Q:1/4=120', 'K:G'
	]
	songbeginning = [x+"\n" for x in songbeginning]

	# convert song to abc format and write to file

	if not os.path.exists(path):
		os.makedirs("gen_songs_abc/song_"+modifier)


	newsong = open(os.path.abspath(songname), 'w')
	newsong.writelines(songbeginning)
	for i in range(lastpart):
		newsong.write(" | ".join(song[i:i+numOfnotes]) + "\n")
	newsong.write(" | ".join(song[lastpart:lengthofsong]))
	newsong.close()
	#abc2ly markov.abc
	# lilypond -fpng markov.ly
	#convert abc to markov
	#create folder with that name and push .ly, midi and abc there?
	

	f = open(song_path+".ly","w")
	# subprocess.Popen(['/usr/bin/abc2midi',songname],stdout=subprocess.PIPE).communicate()
	command = "abc2ly "+"-o "+song_path+".ly"+" "+songname

	# cmd1 = subprocess.Popen(['/usr/bin/abc2ly','-o',song_path+".ly",songname],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
	# cmd1 = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
	subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
	# os.system(command)
	f.close()
	# out, err = cmd1.communicate()
	# # time.sleep(2) 
	cmd2 = subprocess.Popen(['lilypond','-fpng','-o',path,song_path+".ly"]).communicate()
	# cmd2.wait()
	
	#fluidsynth() dependency
	# subprocess.Popen(['midi2audio',song_path+'.midi',song_path+'.wav']).communicate()
	subprocess.Popen(['timidity',song_path+'.midi','-Ow','-o',song_path+'.wav']).communicate()
	# output = str(temp.communicate())
	#Introduces this wait time as we were returning file path even before lilypond converted the abc file
	# final_path = os.path.abspath(song_path+".png")
	png_list = get_pngs(path)
	return png_list,song_path+".wav"