#!/usr/bin/python
# Convert Font Awesome, Google Material Design and Kenney Game icon font
# parameters to C++11 and C89 compatible formats.
#
#------------------------------------------------------------------------------
# 1 - Source material
#
#   1.1 - Font Awesome - https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml
#   1.2 - Material Design - https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/codepoints
#   1.3 - Kenney icons - https://raw.githubusercontent.com/SamBrishes/kenney-icon-font/master/css/kenney-icons.css
#
#------------------------------------------------------------------------------
# 2 - Data samples
#
#   2.1 - Font Awesome
#           - input:          - name:       Music
#                               id:         music
#                               unicode:    f001
#                               created:    1.0
#                               filter:
#                                 - note
#                                 - sound
#                               categories:
#                                 - Web Application Icons
#           - output C++11:     #define ICON_FA_MUSIC u8"\uf001"
#           - output C89:       #define ICON_FA_MUSIC "\xEF\x80\x81"
#
#   2.2 - Google Material Design icons
#           - input:            3d_rotation e84d
#           - output C++11:     #define ICON_MD_3D_ROTATION u8"\ue84d"
#           - output C89:       #define ICON_MD_3D_ROTATION "\xEE\xA1\x8D"
#
#   2.3 - Kenney Game icons
#           - input:            .ki-home:before{ content: "\e900"; }
#           - output C++11:     #define ICON_KI_HOME u8"\ue900"
#           - output C89:       #define ICON_KI_HOME "\xEE\xA4\x80"
#
#   2.4 - All fonts
#           - computed min and max unicode fonts ICON_MIN and ICON_MAX
#           - output:           #define ICON_MIN_FA 0xf000
#                               #define ICON_MAX_FA 0xf295
#
#------------------------------------------------------------------------------
# 3 - Script dependencies
#
#   3.1 - Python 2.7 - https://www.python.org/download/releases/2.7/
#   3.2 - Requests - http://docs.python-requests.org/
#   3.3 - PyYAML - http://pyyaml.org/
#
#------------------------------------------------------------------------------


import requests
import yaml


LINE_FORMAT_MINMAX = '#define ICON_{!s}_{!s} 0x{!s}\n'

UNICODE_MIN = 'ffff'
UNICODE_MAX = '0'
TIMEOUT = 2

MESSAGE_SUCCESS = '{!s} fonts - conversion success: {!s}'
MESSAGE_ERROR = '{!s} fonts - error \n\t{!s}'


def get_prelude( url ):
	prelude = '// Generated by GenerateIconFontCppHeaders.py \n// from {!s}\n#pragma once\n\n'.format( url )
	return prelude


def line_format( font_abbr, font, unicode, cpp11 = True ):
	if cpp11:
		result = '#define ICON_{!s}_{!s} u8"\u{!s}"\n'.format( font_abbr, font, unicode )
	else:
		unicode_base = ''.join([ '{0:x}'.format( ord( x )) for x in unichr( int( unicode, 16 )).encode( 'utf-8' )]).upper()
		unicode = '\\x' + unicode_base[ :2 ] + '\\x' + unicode_base[ 2:4 ] + '\\x' + unicode_base[ 4: ]
		result = '#define ICON_{!s}_{!s} "{!s}"\n'.format( font_abbr, font, unicode )
	return result


def convert_font_awesome( font_name, font_abbr, source_url, output_file, cpp11 ):
	try:
		response = requests.get( source_url, timeout = TIMEOUT )
		if response.status_code == 200:
			input = yaml.safe_load( response.content )
			min = UNICODE_MIN
			max = UNICODE_MAX
			output_fonts = ''
			for item in input[ 'icons' ]:
				font = ''
				for char in item[ 'id' ]:
					font += '_' if ( char == '-' ) else str.upper( char )
				unicode = item[ 'unicode' ]
				if unicode < min:
					min = unicode
				elif unicode >= max:
					max = unicode
				output_fonts += line_format( font_abbr, font, unicode, cpp11 )
			output = get_prelude( source_url ) + \
						LINE_FORMAT_MINMAX.format( 'MIN', font_abbr, min ) + \
						LINE_FORMAT_MINMAX.format( 'MAX', font_abbr, max ) + \
						output_fonts
			with open( output_file, 'w' ) as f:
				f.write( output )
			print( MESSAGE_SUCCESS.format( font_name, output_file ))
	except Exception as e:
		print( MESSAGE_ERROR.format( font_name, e ))


def convert_material_design( font_name, font_abbr, source_url, output_file, cpp11 ):
	try:
		response = requests.get( source_url, timeout = TIMEOUT )
		if response.status_code == 200:
			input = str.split( response.content, '\n' )
			min = UNICODE_MIN
			max = UNICODE_MAX
			output_fonts = ''
			for line in input:
				words = str.split( line )
				if words:
					font = ''
					for char in words[ 0 ]:
						font += '_' if ( char == '-' ) else str.upper( char )
					unicode = words[ 1 ]
					if unicode < min:
						min = unicode
					elif unicode >= max:
						max = unicode
					output_fonts += line_format( font_abbr, font, unicode, cpp11 )
			output = get_prelude( source_url ) + \
						LINE_FORMAT_MINMAX.format( 'MIN', font_abbr, min ) + \
						LINE_FORMAT_MINMAX.format( 'MAX', font_abbr, max ) + \
						output_fonts
			with open( output_file, 'w' ) as f:
				f.write( output )
			print( MESSAGE_SUCCESS.format( font_name, output_file ))
	except Exception as e:
		print( MESSAGE_ERROR.format( font_name, e ))


def convert_kenney( font_name, font_abbr, source_url, output_file, cpp11 ):
	try:
		response = requests.get( source_url, timeout = TIMEOUT )
		if response.status_code == 200:
			input = str.split( response.content, '\n' )
			min = UNICODE_MIN
			max = UNICODE_MAX
			output_fonts = ''
			font_begin= '.ki-'
			font_end = ':before'
			unicode_begin = '"\\'
			unicode_end = '";'
			for line in input:
				words = str.split( line )
				if words:
					if font_begin in words[ 0 ]:
						font = ''
						word = words[ 0 ][( words[ 0 ].find( font_begin ) + len( font_begin )) : ( words[ 0 ].find( font_end ))]
						for char in word:
							font += '_' if ( char == '-' ) else str.upper( char )
						unicode = str( words[ 2 ][( words[ 2 ].find( unicode_begin ) + len( unicode_begin )) : words[ 2 ].find( unicode_end )])
						if unicode < min:
							min = unicode
						elif unicode >= max:
							max = unicode
						output_fonts += line_format( font_abbr, font, unicode, cpp11 )
			output = get_prelude( source_url ) + \
						LINE_FORMAT_MINMAX.format( 'MIN', font_abbr, min ) + \
						LINE_FORMAT_MINMAX.format( 'MAX', font_abbr, max ) + \
						output_fonts
			with open( output_file, 'w' ) as f:
				f.write( output )
			print( MESSAGE_SUCCESS.format( font_name, output_file ))
	except Exception as e:
		print( MESSAGE_ERROR.format( font_name, e ))


# Main

convert_font_awesome( 'Font Awesome', 'FA', 'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml', 'icons_font_awesome.h', False )
convert_material_design( 'Material Design', 'MD', 'https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/codepoints', 'icons_material_design.h', False )
convert_kenney( 'Kenney', 'KI', 'https://raw.githubusercontent.com/SamBrishes/kenney-icon-font/master/css/kenney-icons.css', 'icons_kenney.h', False )
