# -*- coding: iso-8859-1 -*-
"""
GraphViz parser module for MoinMoin
                     
----
Copyright (C) 2007 Zoran Isailovski
Copyright (C) 2008 Remco Boerma 
Licensed under the Apache License, Version 2.0 (see http://www.apache.org/licenses/LICENSE-2.0)
or, at your option, under the terms described in the file LICENSE.txt found in the root of the 
distribution of this package (as far as it denotes a different license then the above).
"""
import os.path
import sha
import re
from MoinMoin.parser import text_moin_wiki
from MoinMoin import wikiutil
from MoinMoin.action import AttachFile

VALID_GRAPHVIZ_TOOLS = 'dot twopi neato circo fdp'.split()

def seek(cmd):
    """Returns the first valid path for cmd in $PATH or None."""
    for directory in os.environ['PATH'].split(os.pathsep):
        filepath = os.path.join(directory,cmd)
        if os.path.exists(filepath):
            return filepath
    return None

class Parser:
    """ MoinMoin graphViz parser."""
    extensions = []
    Dependencies = []

    def __init__(self, raw, request, **kw):
        """ Validate and store arguments provided by Moin.

        self.raw = raw text provided
        self.formatter = formatter provided by the user
        """
        # get the formatter from the 'commandline'
        self.formatter = kw.get('format_args','dot').strip()
        # validate if it's save... 
        if self.formatter.lower() not in VALID_GRAPHVIZ_TOOLS:
            self.error_msg = "%r is not a valid formatter" % \
                             self.formatter
        # if we're on windows: add .exe to make things work 
        if os.name == 'nt':
            self.formatter += ".exe"
        print `self.formatter`
        # set self.formatter to the path leading to the formatter
        self.formatter = seek(self.formatter)
        # provide an error if no file in $PATH could be found
        if self.formatter is None:
            self.error_msg = "Cannot find executable for %r" % \
                             self.formatter
        # store the raw and request for later processing
        self.raw = raw
        self.request = request
        # find the attachments directory for this page
        self.store_attachments_in = \
             request.formatter.page.getPagePath('attachments')
        # investigate whether a map file is required
        self.need_map = raw.find('URL') > -1
        # create a unique identifier within this page
        self.fingerprint = sha.new(raw).hexdigest()
        # calculate the png name
        self.png_filename = os.path.join(self.store_attachments_in,
                                 'diagram-'+self.fingerprint+'.png')
        # calculate the map name
        self.map_filename = os.path.join(self.store_attachments_in,
                                 'diagram-'+self.fingerprint+'.map')


    def generate_files(self):
        """Produce the png file (and optionally the map file)."""
        # check if the cached result is enough
        if os.path.exists(self.png_filename) and \
           (os.path.exists(self.map_filename) or not self.need_map):
            return
        # determine the commandline for generating the image
        cmdline = '%s -Tpng -Gbgcolor=transparent -o %s' % \
                    (self.formatter,self.png_filename)
        p = os.popen(cmdline, 'w')
        p.write(self.raw)
        p.close()
        if self.need_map:
            # if the map file is required create that one as well
            cdmline = '%s -Tcmap -o %s' % \
                      (self.formatter, self.map_filename)
            p = os.popen('dot -Tcmap -o ' + self.map_filename, 'w')
            p.write(self.raw)
            p.close()        

        
    def format(self, formatter):
        if hasattr(self,'error_msg'):
            # handle stored errors by printing them
            # and returning immidiatly
            self.request.write(formatter.text(
                wikiutil.escape(self.error_msg)))
            return
        self.generate_files()
        img_url = AttachFile.getAttachUrl(
                    formatter.page.page_name,
                    os.path.split(self.png_filename)[1],
                    self.request)
        if self.need_map:
            # write html to show the image and linked to a map
            self.request.write(
                formatter.image(src = img_url,
                                usemap = '#' + self.fingerprint,
                                border = 0,
                                ismap = True))
            # read map from disk
            p = open(self.map_filename, 'r')
            map_contents = p.read()
            p.close()
            # write the map html to the stream
            map_html = '<MAP name="'+ self.fingerprint + '">\n'+ \
                       map_contents + '</MAP>'
            self.request.write(formatter.rawHTML(map_html))
        else:
            # write a line to include the graphic
            self.request.write(formatter.image(src = img_url))


##class Snippets:
##    STD_GRAPH_HEADER = '''overlap=false
##    node [fontname=Verdana fontsize=10 style=filled fillcolor=azure color=steelblue fontcolor=steelblue]
##    edge [fontname=Verdana fontsize=8 color=steelblue fontcolor=steelblue]'''
##
##    ATTEMPT_TO_JOIN_EDGES = 'concentrate=true'
##    LEFT_TO_RIGHT = 'rankdir=LR'

