# -*- coding: utf-8 -*-

import os

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


class BlockdiagLoader(object):
    search_builders = ['blockdiag', 'seqdiag', 'actdiag', 'nwdiag', 'rackdiag']

    def __init__(self):
        self._d = {}
        for name in self.search_builders:
            builder = self.make_builder(name) or self.make_legacy_builder(name)
            if builder is not None:
                self._d[name[:-4]] = builder

    def make_builder(self, name):
        try:
            return BlockdiagBuilder(name)
        except ImportError:
            return None

    def make_legacy_builder(self, name):
        try:
            return LegacyBlockdiagBuilder(name)
        except ImportError:
            return None

    def available_builders(self):
        return [x + 'diag' for x in self._d.keys()]

    def __getattr__(self, name):
        return self.__getitem__(name)

    def __getitem__(self, key):
        return self._d[key]


class BlockdiagBuilder(object):
    def __init__(self, name):
        self.name = name
        self.load_module()

    def load_module(self):
        parser = _from_import(self.name, 'parser')
        builder = _from_import(self.name, 'builder')
        drawer = _from_import(self.name, 'drawer')

        # copy needed class/func for easily overriding
        self.parse_string = parser.parse_string
        self.ScreenNodeBuilder = builder.ScreenNodeBuilder
        self.DiagramDraw = drawer.DiagramDraw

    def build(self, text, format, options):
        tree = self.parse_string(text)
        diagram = self.ScreenNodeBuilder.build(tree)
        draw = getattr(self, 'draw_%s' % format.lower())
        return draw(diagram, options)

    def draw_png(self, diagram, options):
        sio = StringIO()
        drawer = self.DiagramDraw('PNG', diagram, sio, **options)
        drawer.draw()
        drawer.save()
        png = sio.getvalue()
        try:
            sio.close()
        except:
            pass
        return png

    def draw_svg(self, diagram, options):
        drawer = self.DiagramDraw('SVG', diagram, None, **options)
        drawer.draw()
        return drawer.save()


class LegacyBlockdiagBuilder(BlockdiagBuilder):
    """Blockdiag Builder for Compatibility"""

    def load_module(self):
        diagparser = _from_import(self.name, 'diagparser')
        builder = _from_import(self.name, 'builder')
        DiagramDraw = _from_import(self.name, 'DiagramDraw')

        self.parse = diagparser.parse
        self.tokenize = diagparser.tokenize
        self.ScreenNodeBuilder = builder.ScreenNodeBuilder
        self.DiagramDraw = DiagramDraw.DiagramDraw

    def parse_string(self, text):
        if isinstance(text, str):
            text = text.decode('utf-8')
        return self.parse(self.tokenize(text))


def _from_import(frm_, imp_):
    return getattr(__import__('%s.%s' % (frm_, imp_)), imp_)


def detectfont(prefer=None):
    prefer = prefer or []
    fonts = prefer + [
        'c:/windows/fonts/VL-Gothic-Regular.ttf',       # for Windows
        'c:/windows/fonts/msmincho.ttf',                # for Windows
        'c:/windows/fonts/msgoth04.ttc',                # for Windows
        '/usr/share/fonts/truetype/ipafont/ipagp.ttf',  # for Debian
        '/usr/local/share/font-ipa/ipagp.otf',          # for FreeBSD
        '/Library/Fonts/Hiragino Sans GB W3.otf',       # for MacOS
        '/System/Library/Fonts/AppleGothic.ttf'         # for MaxOS
    ]
    for font in fonts:
        if font and os.path.isfile(font):
            return font


def get_diag(type_, text, fmt, font=None, antialias=True, nodoctype=False):
    builder = loader[type_]
    options = {'antialias': antialias, 'nodoctype': nodoctype}
    options['font'] = detectfont(font)
    return builder.build(text, fmt, options)


loader = BlockdiagLoader()

@@ -124,16 +124,109 @@
 ringIO%0A%0A
+try:%0A    from blockdiag.utils.fontmap import FontMap%0Aexcept ImportError:%0A    FontMap = None%0A%0A
 %0Aclass B
@@ -1596,32 +1596,239 @@
 er.DiagramDraw%0A%0A
+    def prepare_options(self, options):%0A        options%5B'font'%5D = detectfont(options.get('font', None))%0A        if FontMap is not None:%0A            options%5B'fontmap'%5D = self.create_fontmap(options%5B'font'%5D)%0A%0A
     def build(se
@@ -1847,32 +1847,70 @@
 rmat, options):%0A
+        self.prepare_options(options)%0A
         tree = s
@@ -2538,16 +2538,143 @@
 save()%0A%0A
+    def create_fontmap(self, font):%0A        fontmap = FontMap()%0A        fontmap.set_default_font(font)%0A        return fontmap%0A%0A
 %0Aclass L
@@ -4184,16 +4184,30 @@
 ions = %7B
+'font': font, 
 'antiali
@@ -4250,47 +4250,8 @@
 pe%7D%0A
-    options%5B'font'%5D = detectfont(font)%0A
     

fix font problem