#!/usr/bin/env python3

import sys, os, json, zipfile

#edits an SVG to work around a few rsvg <path>-handling bugs:
# - various abbrevated numbers (like .1 rather than 0.1) are misparsed; https://gitlab.gnome.org/GNOME/librsvg/issues/60
# - 'c' and 's' use wrong offsets (C and S work); no upstream report found
#(yes, they're all fixed upstream, I'm on ubuntu 14.04 i'm old school shut up)
#redoes all compression it undoes, which sometimes (but not always) is smaller than the input; your choice if it's worthwhile
#if you don't care about ancient rsvg bugs, feel free to nop this out
def fixSvg(s):
	#return s
	
	def fixPath(p):
		x = 0
		y = 0
		words = []
		word = ""
		state = 0  # 0: dot allowed in word; 1: dot starts next word
		
		for c in p:
			if c == ' ' or c == ',':
				words.append(word)
				word = ""
				continue  # don't add spaces to the words
			
			if c == '.' and '.' in word:
				words.append(word)
				word = '.'
				continue
			
			if c == '-' and (not word or word[-1]!='e'):
				words.append(word)
				word = '-'
				continue
			
			if c.isalpha() and c!='e':
				words.append(word)
				words.append(c)
				word = ''
				continue
			
			word += c
		words.append(word)
		
		words = [w for w in words if w]
		
		lengths = { 'c':6, 'z':0, 'm':2, 'l':2, 'h':1, 'v':1, 's':4, 'q':4, 't':2, 'a':7 }
		
		shapes = []
		
		i=0
		last = None
		while i < len(words):
			if words[i].isalpha():
				last = words[i]
				i += 1
			
			shapes.append([last] + words[i : i+lengths[last.lower()]])
			i += lengths[last.lower()]
			if last == 'm':  # this specific one is magic... https://www.w3.org/TR/SVG11/paths.html#PathDataMovetoCommands
				last = 'l'
			if last == 'M':
				last = 'L'
		
		def ts(n):
			r="{0:.7f}".format(round(n,2))
			if r[-1]!='0':1/0
			while r[-1]=='0':r=r[:-1]
			while r[-1]=='.':r=r[:-1]
			return r
		
		x = 0
		y = 0
		ox = 0
		oy = 0
		
		for i,s in enumerate(shapes):
			if s[0] in 'qta':  # untested
				print(s)
				1/0
			
			if s[0] == 'c':
				shapes[i] = ['C',
						ts(float(s[1])+x), ts(float(s[2])+y),
						ts(float(s[3])+x), ts(float(s[4])+y),
						ts(float(s[5])+x), ts(float(s[6])+y)
					]
			if s[0] == 's':
				shapes[i] = ['S',
						ts(float(s[1])+x), ts(float(s[2])+y),
						ts(float(s[3])+x), ts(float(s[4])+y)
					]
			#if shapes[i][0] == 'S':
			#	px = float(shapes[i-1][-2])
			#	py = float(shapes[i-1][-1])
			#	if shapes[i-1][0] not in 'CS':
			#		px = x
			#		py = y
			#	shapes[i] = ['C',
			#			ts(x - (px-x)),
			#			ts(y - (py-y)),
			#		] + shapes[i][1:]
			
			if s[0] in 'hvHVzZ':
				if s[0]=='h': x+=float(s[-1])
				if s[0]=='v': y+=float(s[-1])
				if s[0]=='H': x=float(s[-1])
				if s[0]=='V': y=float(s[-1])
				if s[0] in 'zZ':
					x = ox
					y = oy
				continue
			
			if s[0].isupper():
				x=0
				y=0
			x += float(s[-2])
			y += float(s[-1])
			
			if s[0] in 'mM':
				ox = x
				oy = y
		
		last = shapes[0][0]
		for i in range(1,len(shapes)):
			if shapes[i][0] == last and last not in 'mM':
				shapes[i][0] = ""
			else:
				last = shapes[i][0]
		
		words = [i+' ' for l in shapes for i in l if i]
		words[0] = words[0].strip()
		lastnumneg = False
		for i in range(1,len(words)):
			prev = words[i-1]
			cur = words[i]
			if cur.strip().isalpha():
				prev = prev.strip()
				cur = cur.strip()
			if cur[0] == '-':
				prev = prev.strip()
			if cur[0] == '.' and lastnumneg:
				cur = '0'+cur
			if not cur.isalpha():
				lastnumneg = (cur[0] == '-')
			words[i-1] = prev
			words[i] = cur
		return ''.join(words)
	
	split = s.split(' d="') # yes, wanna fight about it?
	for n in range(1,len(split)):
		a = split[n].split('"', 1)
		a[0] = fixPath(a[0])
		split[n] = a[0]+'"'+a[1]
	return ' d="'.join(split)

if sys.argv[1:] and sys.argv[1].endswith(".svg"):
	print(fixSvg(open(sys.argv[1]).read()), end="")

else:
	if not os.path.isfile("gh-pages.zip"):
		print("To compile the emoji list, Twemoji must be downloaded.")
		ans = input("This is a ~450MB zip file. Proceed (Y/n)? ")
		if ans=="" or ans=="y" or ans=="Y":
			os.system("wget https://github.com/twitter/twemoji/archive/gh-pages.zip")
		else:
			print("Cancelled")
			exit(1)
	
	emojis = json.loads(open("emoji-in.json").read())
	
	def vn(v,fn):
		if v==1: return "twemoji-gh-pages/svg/"+fn
		if v==2: return "twemoji-gh-pages/2/svg/"+fn
	
	twemoji = zipfile.ZipFile("gh-pages.zip")
	twemoji_names = set(n for n in twemoji.namelist() if '/svg/' in n)
	with zipfile.ZipFile("discord-emoji.zip", "w", zipfile.ZIP_DEFLATED) as out:
		for emoji in emojis:
			if emoji["unicode"] not in "©®™": # Discord renders those as text, so drop their images
				fn_base = '-'.join(hex(ord(c))[2:] for c in emoji["unicode"])
				fn = fn_base+".svg"
				print(fn)
				v = 1
				if vn(1,fn) not in twemoji_names: v = 2
				#for growing emoji groups (skin tone, family, flags), use v2 only, v1 is ugly
				if vn(1,fn_base+"-1f3fb.svg") not in twemoji_names and \
				   vn(2,fn_base+"-1f3fb.svg")     in twemoji_names: v = 2
				if emoji["names"][0] == ":family:": v = 2
				if emoji["names"][0].startswith(":flag"): v = 2
				out.writestr(fn, fixSvg(twemoji.read(vn(v,fn)).decode("utf-8")))
				emoji["file"] = fn
			else:
				emoji["file"] = None
		
		out.writestr("LICENSE",
			"These SVG files are from the Twemoji set by Twitter, licensed under CC-BY-4.0.\n"+
			"For more information, see <https://github.com/twitter/twemoji>\n")
		out.writestr("emoji.json", json.dumps(emojis, ensure_ascii=False).replace(", ",","))
