"""
Display image in attachment or repository onto the wiki page.
You can use this macro in wiki or ticket module.
First argument is filename (file spec).
Rest of optional arguments are attribute/style string of IMG element.
If it is digits and unit, treat as size (ex. 120, 25%) of IMG.
If it is 'right', 'left', 'top' or 'bottom', treat as align of IMG.
if it is key=value style, treat as attribute of IMG.
if it is key:value style, treat as style of IMG.

Ex.
  [[Image(photo.jpg)]]                          # simplest
  [[Image(photo.jpg,120px)]]                    # with size
  [[Image(photo.jpg,right)]]                    # aligned by keyword
  [[Image(photo.jpg,align=right)]]              # aligned by attribute
  [[Image(photo.jpg,float:right)]]              # aligned by style
  [[Image(photo.jpg,border:solid 5px green)]]   # with any style

You can use image from other page, other ticket or other module.
  [[Image(OtherPage/foo.bmp)]]    # if current module is wiki
  [[Image(base/sub/bar.bmp)]]     # from hierarchical wiki page
  [[Image(3/baz.bmp)]]            # if in a ticket, point to #3
  [[Image(ticket/36/boo.jpg)]]
  [[Image(file/images/bee.jpg)]]
  
"""

import os
import re
import string

from  trac.util import escape

def execute(hdf, txt, env):
    # args will be null if the macro is called without parentesis.
    if not txt:
        return ''
    # parse arguments
    # we expect 1st arguemnt is filename (filespec)
    args = txt.split(',')
    if len(args) == 0:
        raise Exception("No argument.")
    file = args[0]
    size_re = re.compile('^[0-9]+%?$')
    align_re = re.compile('^(?:left|right|top|bottom)$')
    keyval_re = re.compile('^([-a-z0-9]+)([=:])(.*)')
    quoted_re = re.compile("^(?:&#34;|')(.*)(?:&#34;|')$")
    attr = {}
    style = {}
    for arg in args[1:]:
        arg = arg.strip()
        if size_re.search(arg):
            # 'width' keyword
            attr['width'] = arg
            continue
        if align_re.search(arg):
            # 'align' keyword
            attr['align'] = arg
            continue
        match = keyval_re.search(arg)
        if match:
            key = match.group(1)
            sep = match.group(2)
            val = match.group(3)
            m = quoted_re.search(val) # unquote &#34; character "
            if m:
                val = m.group(1)
            if sep == '=':
                attr[key] = val;
            elif sep == ':':
                style[key] = val

    # get current module and id from hdf
    module = hdf.getValue('args.mode', 'wiki')
    if module == 'wiki':
        id = hdf.getValue('args.page', 'WikiStart')
    elif module == 'ticket':
        id = hdf['args.id'] # for ticket
    else:
        # limit of use
        raise Exception('Cannot use this macro in %s module' % module)
    # parse file argument to get module and id if contained.
    # we allow 'file', 'id/file', 'module/id/file' format.
    # id can be dir/dir/node.
    # module can be 'wiki', 'ticket' or 'file'
    # if for file module id (means path) can be omitted.
    parts = file.split('/')
    file = parts.pop() # anyway, last one is filename
    if 0 < len(parts):
        if parts[0] in ['wiki', 'ticket', 'file']:
            # full spec
            id = string.join(parts[1:], '/')
            module = parts[0]
        else:
            # module name is not speciifed
            id = string.join(parts, '/')
    if module == 'file':
        path = "%s/%s" % (id, file)
        url = env.href.file(path)
        raw_url = env.href.file(path, format='raw')
        desc = file
    else:
        url = env.href.attachment(module, id, file)
        raw_url = env.href.attachment(module, id, file, format='raw')
        # get description for file from db.
        cnx = env.get_db_cnx()
        cursor = cnx.cursor()
        cursor.execute("SELECT description from attachment where type='%s' and id='%s' and filename='%s'" % (module, id, file))
        row = cursor.fetchone()
        if row:
            desc = row[0]
        else:
            raise Exception("Attachment is missed: module=%s, id=%s, file=%s" %(module, id, file))

    for key in ['title', 'alt']:
        if desc and not attr.has_key(key):
            attr[key] = desc
    a_style = 'padding:0; border:none' # style of anchor
    img_attr = string.join(map(lambda x: '%s="%s"' % x, attr.iteritems()),
                           ' ')
    img_style = string.join(map(lambda x: "%s:%s" % x, style.iteritems()),
                            ' ')
    return "<a href='%s' style='%s'><img src='%s' %s style=\"%s\" /></a>" % (
        url, a_style, raw_url, img_attr, img_style)

