import os
import sys
import fnmatch
import re

try:
	import urllib.request as urllib2
except ImportError:
	import urllib2

#Convenient methods
def webfileExists(url):
	try:
		response = urllib2.urlopen(urllib2.Request(url)).read(1)
		return True
	except:
		return False

def webfileDownload(url):
	if webfileExists(url):
		lines = []
		
		for line in urllib2.urlopen(url).read(20000):
			lines.append(line)

		for i in range(0, len(lines)):
			lines[i] = chr(lines[i])

		return "".join(lines)
	else:
		return ""

def all_indices(value, qlist):
	indices = []
	idx = -1
	while True:
		try:
			idx = qlist.index(value, idx + 1)
			indices.append(idx)
		except ValueError:
			break
	return indices

#My own code
def testArgs(arguments, argCount, precise):
	if len(arguments[1:]) < argCount:
		print("[ERROR] Not enough arguments. Use -h for help")
		return False
	elif len(arguments[1:]) > argCount and precise == True:
		print("[ERROR] To many arguments. Use -h for help")
		return False
	return True

def showHelp():
	print("Markdown To Html")
	print("Convert markdown to html")
	print("")
	print("Usage: MarkdownToHtml.py {INPUTFILE} [OUTPUTFILE] [OPTIONS]")
	print("")
	print("INPUTFILE:  This must be an .md or .markdown file")
	print("OUTPUTFILE: The name of the generated html file. If none specified this will be the same as the input file")
	print("OPTIONS:")
	print("    -t     Set the title of the webpage")
	print("    -c     Set the charset of the webpage ")
	print("    -i     Include a javascript library. You can use the google libraries or from your own url.")
	print("           Google libraries: AngularJS Angular_Material Dojo Ext-Core Jquery MooTools Prototype scriptaculous SPF SWFobject threejs webfontloader")
	print("           Usage: {libary}{version} or {adress-to-library} e.g. -i jQuery1.11.3 or -i \"https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js\"")
	print("    -d     Download the included libraries")
	print("    -nomin Do not use the minimized versions of the google libraries")
	print("    -a     Include javascript and stylesheets from disk.")
	print("           You can specify a folder; this wil load all files in the folder")
	print("           Or you can specify a .ass or .assets file; The specified files will automaticly be loaded.")
	print("    -nocss This will exclude ALL css from the build")
	print("    -nojs  This will exclude ALL js from the build, including the includes from google")
	#End of help
	return

def readFile(filename, extensions):
	if len(extensions) != 0 and os.path.splitext(filename)[1] not in extensions:
		print("[ERROR] Wrong extension. Use -h for help")
		return []
	elif os.path.exists(filename) and not os.access(os.path.dirname(filename), os.W_OK):
		file = open(filename, 'r')
		buffer = list(file.read())
		if len(buffer) == 0:
			print("[ERROR] File is empty: " + filename)
		file.close()
		return buffer
	else:
		print("[ERROR] Could not open file: " + filename)
		return []

def writeFile(filename, extension,  data):
	file = open(os.path.splitext(filename)[0] + extension, 'w')
	file.write(data)

def convert(buffer, args):
	result = []
	floating_data = []

	#Standard html rules
	result.append("<!DOCTYPE html>" + "\n")
	result.append("<html>" + "\n")

	if len(args) > 0:
		result.append("\t" + "<head>" + "\n")

		if "-t" in args and not fnmatch.fnmatch(args[args.index("-t") + 1], "-?"):
			result.append("\t\t" + "<title>" + args[args.index("-t") + 1] + "</title>" + "\n")

		if "-c" in args and not fnmatch.fnmatch(args[args.index("-c") + 1], "-?"):
			result.append("\t\t" + "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + args[args.index("-c") + 1] + "\">" + "\n")

		if "-i" in args and not "-nojs" in args:
			for i in all_indices("-i", args):
				if fnmatch.fnmatch(args[i + 1], "http://*") or fnmatch.fnmatch(args[i + 1], "https://*"):
					name = args[i + 1].split("/")[len(args[i + 1].split("/")) - 1]

					#Test if it exists
					print("[INFO] Searching for a downloaded version of " + name + "..." + int(80 - len("[INFO] Searching for a downloaded version of " + name + "...")) * " " + " ", end='')
					if os.path.exists("./assets/js/" + name):
						print("[ ok ]")
						continue
					else:
						print("[fail]")

					if "-d" in args:
						#Download the file
						print("[INFO] Downloading " + name + "..." + int(80 - len("[INFO] Downloading " + name + "...")) * " " + " ", end='')
						if webfileExists(args[i + 1]):
							print("[ ok ]")
							writeFile("./assets/js/" + name, ".js", webfileDownload(args[i + 1]))
							result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + name + "\"></script>" + "\n")
						else:
							print("[fail]")
							print("[ERROR] Download failed (" + args[i + 1] + ")")
					else:
						print("[INFO] Validating " + name + "..." + int(80 - len("[INFO] Validating " + name + "...")) * " " + " ", end='')
						if webfileExists(args[i + 1]):
							print("[ ok ]")
							result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + args[i + 1] + "\"></script>" + "\n")
						else:
							print("[fail]")
							print("[ERROR] File not found (" + args[i + 1] + ")")

				elif not fnmatch.fnmatch(args[i + 1], "-?"):
					name1 = name2 = re.split('(\d+)', args[i + 1])[0].lower()
					version = "".join(re.split('(\d+)', args[i + 1])[1:])

					if version == version.replace(".", "") and name1.endswith("r"):
						name1 = name1[0:len(name1) - 1]
						name2 = name2[0:len(name2) - 1]
						version = "r" + version

					#Exceptions (Turned out to be a lot more then expected)
					if name1 == "angular":
						name1 = "angularjs"
					elif name2 == "angularjs":
						name2 = "angular"

					elif name1 == "angular-material":
						name1 = "angular_material"
					elif name2 == "angular_material":
						name2 = "angular-material"

					elif name2 == "dojo":
						name2 = "dojo/dojo"

					elif name2 == "mootools":
						name2 = "mootools-yui-compressed"

					elif name1 == "three":
						name1 = "threejs"
					elif name2 == "threejs":
						name2 = "three"

					elif name1 == "webfontloader":
						name1 = "webfont"
						name2 = "webfont"

					#Test if they exist...
					if "-nomin" in args:
						print("[INFO] Searching for a downloaded version of " + name1 + "." + version + ".js..." + int(80 - len("[INFO] Searching for a downloaded version of " + name1 + "." + version + ".js...")) * " " + " ", end='')
						if os.path.exists("./assets/js/" + name1 + "." + version + ".js"):
							print("[ ok ]")
							continue
						else:
							print("[fail]")
					else:
						print("[INFO] Searching for a downloaded version of " + name1 + "." + version + ".js..." + int(80 - len("[INFO] Searching for a downloaded version of " + name1 + "." + version + ".js...")) * " " + " ", end='')
						if os.path.exists("./assets/js/" + name1 + "." + version + ".min.js"):
							print("[ ok ]")
							continue
						else:
							url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".min.js"

							if os.path.exists("./assets/js/" + name1 + "." + version + ".js"):
								if not webfileExists(url):
									print("[ ok ]")
									continue
							else:
								print("[fail]")

					if "-d" in args:
						#Link the not minimized version if requested
						if "-nomin" in args:
							url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".js"

							print("[INFO] Downloading " + name1 + "." + version + ".js" + "..." + int(80 - len("[INFO] Downloading " + name1 + "." + version + ".js" + "...")) * " " + " ", end='')
							if webfileExists(url):
								print("[ ok ]")
								writeFile("./assets/js/" + name1 + "." + version + ".js", ".js", webfileDownload(url))
								result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + name1 + ".js" + "\"></script>" + "\n")
							else:
								print("[fail]")
								print("[ERROR] Library not found. Try manual url (" + url + ")")
						#Try to link the minized version if exist
						else:
							url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".min.js"

							if webfileExists(url):
								#No cheats allowed remember? :p
								print("[INFO] Downloading " + name1 + "." + version + ".min.js" + "..." + int(80 - len("[INFO] Downloading " + name1 + "." + version + ".min.js" + "...")) * " " + " ", end='')
								print("[ ok ]")
								writeFile("./assets/js/" + name1 + "." + version + ".min.js", ".js", webfileDownload(url))
								result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + name1 + ".min.js" + "\"></script>" + "\n")
							#Minimized version not found. Try to link the full version
							else:
								url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".js"

								print("[INFO] Downloading " + name1 + "." + version + ".js" + "..." + int(80 - len("[INFO] Downloading " + name1 + "." + version + ".js" + "...")) * " " + " ", end='')
								if webfileExists(url):
									print("[ ok ]")
									writeFile("./assets/js/" + name1 + "." + version + ".js", ".js", webfileDownload(url))
									result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + name1 + ".js" + "\"></script>" + "\n")
								else:
									print("[fail]")
									print("[ERROR] Library not found. Try manual url (" + url + ")")
					else:
						#Link the not minimized version if requested
						if "-nomin" in args:
							url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".js"

							print("[INFO] Validating " + name1 + "." + version + ".js" + "..." + int(80 - len("[INFO] Validating " + name1 + "." + version + ".js" + "...")) * " " + " ", end='')
							if webfileExists(url):
								print("[ ok ]")
								result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + url + "\"></script>" + "\n")
							else:
								print("[fail]")
								print("[ERROR] Library not found. Try manual url (" + url + ")")
						#Try to link the minized version if exist
						else:
							url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".min.js"

							if webfileExists(url):
								#Same cheats again... I'm sorry
								print("[INFO] Validating " + name1 + "." + version + ".min.js" + "..." + int(80 - len("[INFO] Validating " + name1 + "." + version + ".min.js" + "...")) * " " + " ", end='')
								print("[ ok ]")
								result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + url + "\"></script>" + "\n")
							#Minimized version not found. Try to link the full version
							else:
								url = "https://ajax.googleapis.com/ajax/libs/" + name1 + "/" + version + "/" + name2 + ".js"

								print("[INFO] Validating " + name1 + "." + version + ".js" + "..." + int(80 - len("[INFO] Validating " + name1 + "." + version + ".js" + "...")) * " " + " ", end='')
								if webfileExists(url):
									print("[ ok ]")
									result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + url + "\"></script>" + "\n")
								else:
									print("[fail]")
									print("[ERROR] Library not found. Try manual url (" + url + ")")

		if "-a" in args and not fnmatch.fnmatch(args[args.index("-a") + 1], "-?"):
			if len(os.path.splitext(args[args.index("-a") + 1])[1]) > 0:
				if os.path.splitext(args[args.index("-a") + 1])[1] in [".ass", ".assets"]:
					assets_buffer = "".join(readFile(args[args.index("-a") + 1], [".ass", ".assets"])).split("\n")
					print(assets_buffer)
				else:
					print("[ERROR] Invalid assets file. Use -h for help")
			elif not ("-nocss" in args and "-nojs" in args):
				if "-nojs" not in args:
					for dirpath, dirnames, filenames in os.walk(args[args.index("-a") + 1]):
						for filename in [f for f in filenames if f.endswith(".js")]:
							result.append("\t\t" + "<script type=\"text/javascript\" src=\"" + dirpath.replace("\\", "/") + "/" + filename + "\"></script>" + "\n")

				if "-nocss" not in args:
					for dirpath, dirnames, filenames in os.walk(args[args.index("-a") + 1]):
						for filename in [f for f in filenames if f.endswith(".css")]:
							result.append("\t\t" + "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + dirpath.replace("\\", "/") + "/" + filename + "\" />" + "\n")
			else:
				print("[ERROR] Completely useless argument... (-a -nojs -nocss)")

		result.append("\t" + "</head>" + "\n")

	result.append("\t" + "<body>" + "\n")

	print("[INFO] Constructing body..." + int(80 - len("[INFO] Constructing body...")) * " " + " ", end='')
	inPre = False
	inTag = False
	for each in "".join(buffer).split("\n"):
		#Test if in pre
		if inPre == True:
			if "</pre>" in each:
				result.append("\t\t" + "</pre>" + "\n")
				inPre = False
				continue
			else:
				result.append("\t\t\t" + each + "\n")
				continue
		elif "<pre" in each:
			result.append("\t\t" + each.strip() + "\n")
			inPre = True
			continue

		#if each is in tag
		if fnmatch.fnmatch(each.strip(), "<*>"):
			result.append("\t\t\t" + each + "\n")
			inTag = True
		if inTag == True:
			if fnmatch.fnmatch(each.strip(), "</*>"):
				inTag = False
				continue
			else:
				continue

		#Add the link with title to the floating data
		if fnmatch.fnmatch(each.strip(), '[[]*[]]:*\"*\"'):
			floating_data.append([ each[each.find("[") + 1:each.find("]")], each[each.find(":") + 1:each.find("\"")].strip(), each[each.find("\"") + 1:len(each.rstrip()) - 1] ])
			continue

		#Add the link without title to the floating data
		elif fnmatch.fnmatch(each.strip(), '[[]*[]]:*'):
			floating_data.append([ each[each.find("[") + 1:each.find("]")], each[each.find(":") + 1:len(each.rstrip())].strip(), "" ])
			continue

		#Identation system
		splitted_buffer = "".join(buffer).split("\n")
		if splitted_buffer[splitted_buffer.index(each) - 1].find("* ", 0, len(splitted_buffer[splitted_buffer.index(each) - 1])) + 2 == len(each) - len(each.lstrip()) or splitted_buffer[splitted_buffer.index(each) - 1].find("+ ", 0, len(splitted_buffer[splitted_buffer.index(each) - 1])) + 2 == len(each) - len(each.lstrip()) or splitted_buffer[splitted_buffer.index(each) - 1].find("- ", 0, len(splitted_buffer[splitted_buffer.index(each) - 1])) + 2 == len(each) - len(each.lstrip()) or (len(splitted_buffer[splitted_buffer.index(each) - 1]) - len(splitted_buffer[splitted_buffer.index(each) - 1].lstrip()) == len(each) - len(each.lstrip()) and len(each) - len(each.lstrip()) > 0):
			if "</ul>" in result[len(result) - 1]:
				#Change into multiline list
				if "<li>" in result[len(result) - 2] and "</li>" in result[len(result) - 2]:
					result.append("\t\t\t\t" + each.lstrip() + "\n")
					result.append("\t\t\t" + "</li>" + "\n")
					result.append("\t\t" + "</ul>" + "\n")
					result[len(result) - 4] = "\t\t\t\t" + result[len(result) - 5][7:len(result[len(result) - 5]) - 6] + "\n"
					result[len(result) - 5] = "\t\t\t" + "<li>" + "\n"
				#Extend multiline list
				elif not "<li>" in result[len(result) - 2] and "</li>" in result[len(result) - 2]:
					result[len(result) - 2] = "\t\t\t\t" + each.lstrip() + "\n"
					result[len(result) - 1] = "\t\t\t" + "</li>" + "\n"
					result.append("\t\t" + "</ul>" + "\n")
				continue

		splitted_buffer = "".join(buffer).split("\n")
		if len(splitted_buffer[splitted_buffer.index(each) - 1].strip().replace(".","")) > 0 and splitted_buffer[splitted_buffer.index(each) - 1].strip().replace(".","")[0].isdigit() or (len(splitted_buffer[splitted_buffer.index(each) - 1]) - len(splitted_buffer[splitted_buffer.index(each) - 1].lstrip()) == len(each) - len(each.lstrip()) and len(each) - len(each.lstrip()) > 0):
			if "</ol>" in result[len(result) - 1] or "</ol>" in result[len(result) - 2]:
				#Change into multiline list
				if "<li>" in result[len(result) - 2] and "</li>" in result[len(result) - 2]:
					result.append("\t\t\t\t" + each.lstrip() + "\n")
					result.append("\t\t\t" + "</li>" + "\n")
					result.append("\t\t" + "</ol>" + "\n")
					result[len(result) - 4] = "\t\t\t\t" + result[len(result) - 5][7:len(result[len(result) - 5]) - 6] + "\n"
					result[len(result) - 5] = "\t\t\t" + "<li>" + "\n"
				#Extend multiline list
				elif not "<li>" in result[len(result) - 2] and "</li>" in result[len(result) - 2]:
					result[len(result) - 2] = "\t\t\t\t" + each.lstrip() + "\n"
					result[len(result) - 1] = "\t\t\t" + "</li>" + "\n"
					result.append("\t\t" + "</ol>" + "\n")
				continue

		#The indented code blocks	 	
		if len(each) - len(each.lstrip()) >= 4:
			each = each.replace("<", "&lt;").replace(">", "&gt;")
			if len(each.replace(" ", "")) > 0:
				#Change into multiline paragraph
				if "<pre>" in result[len(result) - 1] and "</pre>" in result[len(result) - 1]:
					result.append("\t\t\t" + result[len(result) - 1][7:len(result[len(result) - 1]) - 7] + "\n")
					result.append("\t\t\t" + each[4:len(each)] + "\n")
					result.append("\t\t" + "</pre>" + "\n")
					#change the old line
					result[len(result) - 4] = "\t\t" + "<pre>" + "\n";
				#Extend multiline paragraph
				elif not "<pre>" in result[len(result) - 1] and "</pre>" in result[len(result) - 1]:
					result[len(result) - 1] = "\t\t\t" + each[4:len(each)] + "\n"
					result.append("\t\t" + "</pre>" + "\n")
				#Old fasioned singleline paragraph
				else:
					result.append("\t\t" + "<pre>" + each[4:len(each)] + "</pre>" + "\n")
				continue

		#Standard h6
		if "######" in each and each.strip().replace("#", "") == "":
			token_pos = each.find("######", 0, len(each)) + 6
			result.append("\t\t" + "<h6>" + each[token_pos:len(each)] + "</h6>" + "\n")
		#Standard h5
		elif "#####" in each and each.strip().replace("#", "") == "":	
			token_pos = each.find("#####", 0, len(each)) + 5
			result.append("\t\t" + "<h5>" + each[token_pos:len(each)] + "</h5>" + "\n")
		#Standard h4
		elif "####" in each and each.strip().replace("#", "") == "":
			token_pos = each.find("####", 0, len(each)) + 4
			result.append("\t\t" + "<h4>" + each[token_pos:len(each)] + "</h4>" + "\n")
		#Standard h3
		elif "###" in each and each.strip().replace("#", "") == "":
			token_pos = each.find("###", 0, len(each)) + 3
			result.append("\t\t" + "<h3>" + each[token_pos:len(each)] + "</h3>" + "\n")
		#Standard h2
		elif "##" in each and each.strip().replace("#", "") == "":
			token_pos = each.find("##", 0, len(each)) + 2
			result.append("\t\t" + "<h2>" + each[token_pos:len(each)] + "</h2>" + "\n")
		#Standard h1
		elif "#" in each and each.strip().replace("#", "") == "":
			token_pos = each.find("#", 0, len(each)) + 1
			result.append("\t\t" + "<h1>" + each[token_pos:len(each)] + "</h1>" + "\n")
		#Alternative h1
		elif each.strip().replace("=", "") == "" and "=" in each:
			result[len(result) - 1] = "\t\t" + "<h1>" + result[len(result) - 1][5:len(result[len(result) - 1]) - 5].strip() + "</h1>" + "\n"
		#Alternative h2
		elif each.strip().replace("-", "") == "" and "-" in each:
			result[len(result) - 1] = "\t\t" + "<h2>" + result[len(result) - 1][5:len(result[len(result) - 1]) - 5].strip() + "</h2>" + "\n"

		#Unorganized list
		elif each.strip()[0:2] == "* " or each.strip()[0:2] == "+ " or each.strip()[0:2] == "- ":
			if "* " in each:
				token_pos = each.find("* ", 0, len(each)) + 2
			elif "+ " in each:
				token_pos = each.find("+ ", 0, len(each)) + 2
			elif "- " in each:
				token_pos = each.find("- ", 0, len(each)) + 2

			if "</ul>" in result[len(result) - 1]:
				result[len(result) - 1] = "\t\t\t" + "<li>" + each[token_pos:len(each)].lstrip() + "</li>" + "\n"
				result.append("\t\t" + "</ul>" + "\n")
			else:
				result.append("\t\t" + "<ul>" + "\n")
				result.append("\t\t\t" + "<li>" + each[token_pos:len(each)].lstrip() + "</li>" + "\n")
				result.append("\t\t" + "</ul>" + "\n")

		#Organized list
		elif len(each.strip().replace(".","")) > 0 and each.strip().replace(".","")[0].isdigit():
			if fnmatch.fnmatch(each.strip()[0:2], "? "):
				token_pos = len(each) - len(each.lstrip()) + 2
			elif fnmatch.fnmatch(each.strip()[0:3], "?? ") or fnmatch.fnmatch(each.strip()[0:3], "?. "):
				token_pos = len(each) - len(each.lstrip()) + 3
			elif fnmatch.fnmatch(each.strip()[0:4], "??. "):
				token_pos = len(each) - len(each.lstrip()) + 4

			if "</ol>" in result[len(result) - 1]:
				result[len(result) - 1] = "\t\t\t" + "<li>" + each[token_pos:len(each)].lstrip() + "</li>" + "\n"
				result.append("\t\t" + "</ol>" + "\n")
			else:
				result.append("\t\t" + "<ol>" + "\n")
				result.append("\t\t\t" + "<li>" + each[token_pos:len(each)].lstrip() + "</li>" + "\n")
				result.append("\t\t" + "</ol>" + "\n")

		elif each != "" and each.strip()[0] == ">":
			result.append("\t\t" + "<blockquote>" + each.lstrip()[1:len(each.lstrip())] + "</blockquote>" + "\n")

		#And eventually place the rest of the text in paragraphs
		elif len(each.replace(" ", "")) > 0:
			#Change into multiline paragraph
			if "<p>" in result[len(result) - 1] and "</p>" in result[len(result) - 1]:
				result.append("\t\t\t" + result[len(result) - 1][5:len(result[len(result) - 1]) - 5] + "\n")
				result.append("\t\t\t" + each + "\n")
				result.append("\t\t" + "</p>" + "\n")
				#change the old line
				result[len(result) - 4] = "\t\t" + "<p>" + "\n";
			#Extend multiline paragraph
			elif not "<p>" in result[len(result) - 1] and "</p>" in result[len(result) - 1]:
				result[len(result) - 1] = "\t\t\t" + each + "\n"
				result.append("\t\t" + "</p>" + "\n")
			#Old fasioned singleline paragraph
			else: