#!/opt/local/Library/Frameworks/Python.framework/Versions/3.12/bin/python3.12

# Generate highway shields as SVG files in symbols/shields.

from __future__ import print_function
import copy, lxml.etree, math, os
from generate_road_colours import load_settings, generate_colours

def main():

    settings = load_settings()
    colours = generate_colours(settings, 'shield')

    namespace = 'http://www.w3.org/2000/svg'
    svgns = '{' + namespace + '}'
    svgnsmap = {None: namespace}

    config = {}
    config['base'] = {}

    # font_height and font_width are determined by trial and error
    config['base']['rounded_corners'] = 2
    config['base']['font_height'] = 12.1
    config['base']['font_width'] = 6.2
    config['base']['padding_x'] = 4
    config['base']['padding_y'] = 2
    config['base']['stroke_width'] = 1

    # Fall back colours used if no colours are defined in road-colours.yaml for a road type.
    config['base']['fill'] = '#f1f1f1'
    config['base']['stroke_fill'] = '#c6c6c6'

    config['global'] = {}

    config['global']['types'] = ['motorway', 'trunk', 'primary', 'secondary', 'tertiary']
    config['global']['max_width'] = 11
    config['global']['max_height'] = 4
    config['global']['output_dir'] = '../symbols/shields/' # specified relative to the script location

    config['global']['additional_sizes'] = ['base', 'z16', 'z18']

    # specific values overwrite config['base'] ones
    config['motorway'] = {}
    config['trunk'] = {}
    config['primary'] = {}
    config['secondary'] = {}
    config['tertiary'] = {}

    # Colour values generated by generate_road_colours.py.
    for line_name, line_colours in colours.items():
        for name, colour in line_colours.items():
            config[name][line_name] = colour.rgb()

    # changes for different size versions
    config['z16'] = {}
    config['z18'] = {}

    config['z16']['font_width'] = 6.1
    config['z16']['font_height'] = 14.1
    config['z18']['font_width'] = 6.9
    config['z18']['font_height'] = 15.1

    if not os.path.exists(os.path.dirname(config['global']['output_dir'])):
        os.makedirs(os.path.dirname(config['global']['output_dir']))

    for height in range(1, config['global']['max_height'] + 1):
        for width in range(1, config['global']['max_width'] + 1):
            for shield_type in config['global']['types']:

                # merge base config and specific styles
                vars = copy.deepcopy(config['base'])
                if shield_type in config:
                    for option in config[shield_type]:
                        vars[option] = config[shield_type][option]

                for shield_size in config['global']['additional_sizes']:

                    if shield_size != 'base':
                        if shield_size in config:
                            for option in config[shield_size]:
                                vars[option] = config[shield_size][option]

                    shield_width = 2 * vars['padding_x'] + math.ceil(vars['font_width'] * width)
                    shield_height = 2 * vars['padding_y'] + math.ceil(vars['font_height'] * height)

                    svg = lxml.etree.Element('svg', nsmap=svgnsmap)
                    svg.set('width', str(shield_width + vars['stroke_width']))
                    svg.set('height', str(shield_height + vars['stroke_width']))
                    svg.set('viewBox', '0 0 ' + str(shield_width + vars['stroke_width']) + ' ' + str(shield_height + vars['stroke_width']))

                    if vars['stroke_width'] > 0:
                        offset_x = vars['stroke_width'] / 2.0
                        offset_y = vars['stroke_width'] / 2.0
                    else:
                        offset_x = 0
                        offset_y = 0

                    shield = lxml.etree.Element(svgns + 'rect')
                    shield.set('x', str(offset_x))
                    shield.set('y', str(offset_y))
                    shield.set('width', str(shield_width))
                    shield.set('height', str(shield_height))
                    if vars['rounded_corners'] > 0:
                        shield.set('rx', str(vars['rounded_corners']))
                        shield.set('ry', str(vars['rounded_corners']))

                    shield.set('fill', vars['fill'])

                    stroke = ''
                    if vars['stroke_width'] > 0:
                        shield.set('stroke', vars['stroke_fill'])
                        shield.set('stroke-width', str(vars['stroke_width']))

                    svg.append(shield)

                    filename = shield_type + '_' + str(width) + 'x' + str(height)
                    if shield_size != 'base':
                        filename = filename + '_' + shield_size

                    filename = filename + '.svg'

                    # save file
                    try:
                        shieldfile = open(os.path.join(os.path.dirname(__file__), config['global']['output_dir'] + filename), 'wb')
                        shieldfile.write(lxml.etree.tostring(svg, encoding='utf-8', xml_declaration=True, pretty_print=True))
                        shieldfile.close()
                    except IOError:
                        print('Could not save file ' + filename + '.')
                        continue

if __name__ == "__main__":
    main()
