#!/usr/bin/python

import optparse
import os
import re
import sys

import cairo
from gaphas.painter import Context, ItemPainter
from gaphas.view import View

import gaphor.UML as UML
from gaphor.application import Application
from gaphor.storage import storage


def pkg2dir(package):
    """
    Return directory path from UML package class.
    """
    name = []
    while package:
        name.insert(0, package.name)
        package = package.package
    return "/".join(name)


def paint(view, cr):
    view.painter.paint(Context(cairo=cr, items=view.canvas.get_all_items(), area=None))


def main(argv=sys.argv[1:]):
    def message(msg):
        """
        Print message if user set verbose mode.
        """
        if options.verbose:
            print(msg, file=sys.stderr)

    usage = "usage: %prog [options] file1 file2..."

    parser = optparse.OptionParser(usage=usage)

    parser.add_option(
        "-v", "--verbose", dest="verbose", action="store_true", help="verbose output"
    )
    parser.add_option(
        "-u",
        "--use-underscores",
        dest="underscores",
        action="store_true",
        help="use underscores instead of spaces for output filenames",
    )
    parser.add_option(
        "-d", "--dir", dest="dir", metavar="directory", help="output to directory"
    )
    parser.add_option(
        "-f",
        "--format",
        dest="format",
        metavar="format",
        help="output file format, default pdf",
        default="pdf",
        choices=["pdf", "svg", "png"],
    )
    parser.add_option(
        "-r",
        "--regex",
        dest="regex",
        metavar="regex",
        help="process diagrams which name matches given regular expresion;"
        " name includes package name; regular expressions are case insensitive",
    )

    (options, args) = parser.parse_args(argv)

    if not args:
        parser.print_help()

    Application.init(
        services=["event_manager", "component_registry", "element_factory"]
    )
    factory = Application.get_service("element_factory")

    name_re = None
    if options.regex:
        name_re = re.compile(options.regex, re.I)

    # we should have some gaphor files to be processed at this point
    for model in args:
        message(f"loading model {model}")
        storage.load(model, factory)
        message("ready for rendering")

        for diagram in factory.select(lambda e: e.isKindOf(UML.Diagram)):
            odir = pkg2dir(diagram.package)

            # just diagram name
            dname = diagram.name
            # full diagram name including package path
            pname = f"{odir}/{dname}"

            if options.underscores:
                odir = odir.replace(" ", "_")
                dname = dname.replace(" ", "_")

            if name_re and not name_re.search(pname):
                message(f"skipping {pname}")
                continue

            if options.dir:
                odir = f"{options.dir}/{odir}"

            outfilename = f"{odir}/{dname}.{options.format}"

            if not os.path.exists(odir):
                message(f"creating dir {odir}")
                os.makedirs(odir)

            message(f"rendering: {pname} -> {outfilename}...")

            view = View(diagram.canvas)
            view.painter = ItemPainter()

            tmpsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0)
            tmpcr = cairo.Context(tmpsurface)
            view.update_bounding_box(tmpcr)
            tmpcr.show_page()
            tmpsurface.flush()

            w, h = view.bounding_box.width, view.bounding_box.height
            if options.format == "pdf":
                surface = cairo.PDFSurface(outfilename, w, h)
            elif options.format == "svg":
                surface = cairo.SVGSurface(outfilename, w, h)
            elif options.format == "png":
                surface = cairo.ImageSurface(
                    cairo.FORMAT_ARGB32, int(w + 1), int(h + 1)
                )
            else:
                assert False, f"unknown format {options.format}"
            cr = cairo.Context(surface)
            view.matrix.translate(-view.bounding_box.x, -view.bounding_box.y)
            paint(view, cr)
            cr.show_page()

            if options.format == "png":
                surface.write_to_png(outfilename)

            surface.flush()
            surface.finish()

[((42, 13, 42, 47), 'optparse.OptionParser', 'optparse.OptionParser', (), '', False, 'import optparse\n'), ((80, 4, 82, 5), 'gaphor.application.Application.init', 'Application.init', (), '', False, 'from gaphor.application import Application\n'), ((83, 14, 83, 56), 'gaphor.application.Application.get_service', 'Application.get_service', ({(83, 38, 83, 55): '"""element_factory"""'}, {}), "('element_factory')", False, 'from gaphor.application import Application\n'), ((87, 18, 87, 49), 're.compile', 're.compile', ({(87, 29, 87, 42): 'options.regex', (87, 44, 87, 48): 're.I'}, {}), '(options.regex, re.I)', False, 'import re\n'), ((92, 8, 92, 36), 'gaphor.storage.storage.load', 'storage.load', ({(92, 21, 92, 26): 'model', (92, 28, 92, 35): 'factory'}, {}), '(model, factory)', False, 'from gaphor.storage import storage\n'), ((122, 19, 122, 39), 'gaphas.view.View', 'View', ({(122, 24, 122, 38): 'diagram.canvas'}, {}), '(diagram.canvas)', False, 'from gaphas.view import View\n'), ((123, 27, 123, 40), 'gaphas.painter.ItemPainter', 'ItemPainter', ({}, {}), '()', False, 'from gaphas.painter import Context, ItemPainter\n'), ((125, 25, 125, 70), 'cairo.ImageSurface', 'cairo.ImageSurface', ({(125, 44, 125, 63): 'cairo.FORMAT_ARGB32', (125, 65, 125, 66): '0', (125, 68, 125, 69): '0'}, {}), '(cairo.FORMAT_ARGB32, 0, 0)', False, 'import cairo\n'), ((126, 20, 126, 45), 'cairo.Context', 'cairo.Context', ({(126, 34, 126, 44): 'tmpsurface'}, {}), '(tmpsurface)', False, 'import cairo\n'), ((142, 17, 142, 39), 'cairo.Context', 'cairo.Context', ({(142, 31, 142, 38): 'surface'}, {}), '(surface)', False, 'import cairo\n'), ((116, 19, 116, 39), 'os.path.exists', 'os.path.exists', ({(116, 34, 116, 38): 'odir'}, {}), '(odir)', False, 'import os\n'), ((118, 16, 118, 33), 'os.makedirs', 'os.makedirs', ({(118, 28, 118, 32): 'odir'}, {}), '(odir)', False, 'import os\n'), ((133, 26, 133, 61), 'cairo.PDFSurface', 'cairo.PDFSurface', ({(133, 43, 133, 54): 'outfilename', (133, 56, 133, 57): 'w', (133, 59, 133, 60): 'h'}, {}), '(outfilename, w, h)', False, 'import cairo\n'), ((135, 26, 135, 61), 'cairo.SVGSurface', 'cairo.SVGSurface', ({(135, 43, 135, 54): 'outfilename', (135, 56, 135, 57): 'w', (135, 59, 135, 60): 'h'}, {}), '(outfilename, w, h)', False, 'import cairo\n')]