"""
    MoinMoin - AttachTable Macro
    
    A macro to produce a table of files attached to a page.

    Usage:
       [[AttachTable]]
       [[AttachTable(page=FrontPage, preview=1)]]
       [[AttachTable(readonly=1, closed=1, syntax=1]]

    args:
       @page=string display the attachemnt table for a different page
       @preview=1 if the attachment is a jpg/gif/png file, show a thumbnail image
       @syntax=1 display the wiki syntax how to reference to an attachment
       @closed=0 display the table in a closed/open state overriding the default cfg value 'attach_table_compact'
       @readonly=0 force the display the table in a readonly mode, i.e. remove the 'delete attachment' option

    @copyright: 2007 Oliver Siemoneit
    @copyright: 2006 Erick Martin, Oliver Siemoneit
    @copyright: 2004 Jacob Cohen, Nigel Metheringham
    @license: GNU GPL, see COPYING for details.

"""

import os, urllib, time, random
from MoinMoin import config, wikiutil
from MoinMoin.action.AttachFile import getAttachDir, getAttachUrl
from MoinMoin.Page import Page

def _get_files(base_dir):
    if os.path.isdir(base_dir):
        files = map(lambda a: a.decode(config.charset), os.listdir(base_dir))
        files.sort()
        return files
    return []

def _table_row(d):
    row = ('   <tr style="display:">\n'
           '      <td>\n'
           '        %(data_1)s\n'
           '        <p>\n'
           '        %(data_2)s\n'
           '      </td>\n'
           '      <td> %(data_3)s </td>\n'
           '      <td> %(data_4)s </td>\n'
           '      <td> %(data_5)s </td>\n'
           '   </tr>\n') % d
    return row

def make_thumbnail(request, formatter, attachment_url, ext):
    _ = request.getText
    kw = {}
    alt, icon, w, h = request.theme.icons[ext]
    kw['src'] = attachment_url
    kw['alt'] = _(alt)
    kw['height'] = h
    # display problems: Opera would also need width
    #kw['width'] = (h / orig_h) * orig_w
    return "%s" % formatter.image(**kw)

def file_table(formatter, request, base_dir, pagename, preview_images=0, display_table_closed=0, display_attach_syntax=1, readonly=0):
    _ = request.getText
    attachments = _get_files(base_dir)
    action = 'AttachFile'
    page_url = wikiutil.quoteWikinameURL(pagename)

    # wikiutil.link_tag does not support title so we do it long hand
    manage_url = '<a href="%(baseurl)s/%(page_url)s?action=%(action)s" title="%(title)s" alt="%(title)s">%(text)s</a>' % {
        'baseurl': request.getScriptname(),
        'page_url': page_url,
        'action': action,
        'text': _('Add/Manage'),
        'title': _('Add/Manage uploaded files'), }

    if not attachments and Page(request, pagename).exists() == False:
        return _(u"\n%(icon)s %(manage_url)s files for the '''%(pagename)s''' page ''[No such page]''\n") % {
                   'icon': request.theme.make_icon('table-null'),
                   'pagename': pagename,
                   'manage_url': manage_url, }

    if not attachments:
        return _(u"\n%(icon)s %(manage_url)s files for the '''%(pagename)s''' page\n") % {
                   'icon': request.theme.make_icon('table-null'),
                   'pagename': pagename,
                   'manage_url': manage_url, }

    label_del = _("delete")
    label_get = _("download")
    label_edit = _("edit")
    label_view = _("view")

    table_closed_file_name = 'table-open.png'
    table_open_file_name = 'table-close.png'

    open_image = request.theme.img_url(table_open_file_name)
    closed_image = request.theme.img_url(table_closed_file_name)

    javascript_function = """
// Toggle display of a folder's contents.
function showHideContents ( idnum ) {
   the_table = document.getElementById( 't' + idnum );

   arrowObj  = document.getElementById( 'a' + idnum );
   // we use the image to determine if the table is open or closed
   if (arrowObj.src.indexOf('%(table_open_file_name)s') > -1) {
      arrowObj.src = '%(closed_image)s';
      display      = 'none';
   } else {
      arrowObj.src = '%(open_image)s';
      display      = '';
   }

   // change the open/closed state of the rows for the table
   for (var i = 0; i < the_table.rows.length; i++) {
      the_table.rows[i].style.display = display;
   }
}
""" % {'closed_image': closed_image,
       'open_image': open_image,
       'table_open_file_name': table_open_file_name, }

    html = ("\n"
            '<script type="text/javascript">' "\n"
            "<!--\n"
            "%(javascript_function)s\n"
            "--> </script>\n"
            "\n" ) % {'javascript_function': javascript_function, }


    file_id = random.randint(1, 99999999999)

    html = html + '\n<div class="attachmentTable" >\n'

    table_caption1 = ('<a onClick="showHideContents(%(file_id)s);" title="%(alt_title)s">'
                      '<img id="a%(file_id)s" align="middle" border=0 src="%(open_image)s"'
                      'alt="%(alt_title)s"></a>\n') % {
                      'file_id':  file_id,
                      'alt_title': _("Click to open/close table"),
                      'open_image': open_image, }
    
    table_caption2 = _(u"%(manage_url)s files for the '''%(pagename)s''' page ''[%(num_files)s file(s)]''") % {
                     'num_files':  len(attachments),
                     'pagename': pagename,
                     'manage_url': manage_url, }

    table_caption = table_caption1 + table_caption2

    if display_attach_syntax:
        html = html + ('<br>\n'
                       '%(table_caption)s\n'
                       '<table id="t%(file_id)s" >\n'
                       '   <tr style="display:">\n'
                       '     <th>%(name)s<p>%(syntax)s</th>\n'
                       '     <th>%(size)s</th>\n'
                       '     <th>%(date)s</th>\n'
                       '     <th>%(action)s</th>\n'
                       '   </tr>\n') % {
                          'file_id': file_id,
                          'table_caption': table_caption,
                          'name': _('Name'),
                          'syntax': _('Wiki Include Syntax'),
                          'size': _('Size'),
                          'date': _('Date'),
                          'action': _('Action'),}
    else:
        html = html + ('<br>\n'
                       '%(table_caption)s\n'
                       '<table id="t%(file_id)s" >\n'
                       '   <tr style="display:">\n'
                       '     <th>%(name)s</th>\n'
                       '     <th>%(size)s</th>\n'
                       '     <th>%(date)s</th>\n'
                       '     <th>%(action)s</th>\n'
                       '   </tr>\n') % {
                          'file_id':  file_id,
                          'table_caption':  table_caption,
                          'name': _('Name'),
                          'size': _('Size'),
                          'date': _('Date'),
                          'action': _('Action'),}

    # if user can't delete, force readonly mode
    if not request.user.may.delete(pagename):
        readonly = 1

    for attachment in attachments:
        fsize = float(os.stat(os.path.join(base_dir, attachment).encode(config.charset))[6]) # in byte
        mtime = os.stat(os.path.join(base_dir, attachment).encode(config.charset))[8]
        fsize = "%.1f" % (fsize/1024)
        fdate = time.ctime(mtime)
        urlfile = urllib.quote_plus(attachment.encode(config.charset))

        # build translation for datetime object
        _fdate = fdate.split(' ')
        _fdate[0] = _(_fdate[0])
        _fdate[1] = _(_fdate[1])
        fdate = _("%(day)s %(month)s %(date)s %(time)s %(year)s") % { 'day': _fdate[0],
                                                                      'month': _fdate[1],
                                                                      'date': _fdate[2],
                                                                      'time': _fdate[3],
                                                                      'year': _fdate[4], }

        base, ext = os.path.splitext(attachment)
        get_url = getAttachUrl(pagename, attachment, request, escaped=1)
        parmdict = {'page_url': page_url, 'action': action,
                    'urlfile': urlfile, 'label_del': label_del,
                    'base': base, 'label_edit': label_edit,
                    'label_view': label_view,
                    'get_url': get_url, 'label_get': label_get,
                    'file': attachment, 'fsize': fsize,
                    'pagename': pagename, }

        del_link = ''
        if not readonly:
            action_args = 'do=del&amp;target=%(urlfile)s' % {'urlfile' : urlfile, }
            url = '%(page_url)s?action=%(action)s&amp;%(action_args)s' % {
               'page_url': page_url,
               'action': action,
               'action_args': action_args, }
            del_link = wikiutil.link_tag(request, url, text=label_del,
                                         formatter=request.formatter)


        if ext == '.draw':
            action_args = 'drawing=%(base)s' % {'base': base, }
            url = '%(page_url)s?action=%(action)s&amp;%(action_args)s' % {
               'page_url': page_url,
               'action': action,
               'action_args': action_args, }
            
            viewlink = wikiutil.link_tag(request, url, text=label_edit,
                                         formatter=request.formatter)
        else:
            action_args = 'do=view&amp;target=%(urlfile)s' % {'urlfile': urlfile, }
            url = '%(page_url)s?action=%(action)s&amp;%(action_args)s' % {
               'page_url': page_url,
               'action': action,
               'action_args': action_args, }
            viewlink = wikiutil.link_tag(request, url, text=label_view,
                                         formatter=request.formatter)

        #build file or preview icon
        ext = ext.lower()
        do_preview = False
        #check if we have an icon for the extension
        if ext in request.theme.icons:
            if not preview_images:
                ext = ext
            else:
                if ext in ['.jpg', '.jpeg', '.jpe', '.gif', '.png']:
                    do_preview = True
        # if not: check whether ext belongs to a generic mimetype class
        elif ext in ['.py', '.js', '.jar', '.diff', '.patch']:
            ext = 'generic-text-x-source'
        elif ext in ['.tar', '.zip', '.bz2', '.rar', '.gz', '.cab', '.lha', '.arj']:
            ext = 'generic-x-archive'
        elif ext in ['.wav', '.aif', '.aifc', '.aiff', '.midi', '.mid', '.au']:
            ext = 'generic-x-audio'
        elif ext in ['.jpg', '.jpeg', '.jpe', '.gif', '.png']:
            ext = 'generic-x-image'
            if preview_images:
                do_preview = True
        elif ext in ['.bmp', '.ps', '.eps', '.cdr', '.pct', '.mac', '.drw', '.svg']:
            ext = 'generic-x-image'
        elif ext in ['.mpeg', '.mpg', '.wmv', '.avi', '.mov', '.movie', '.qt']:
            ext = 'generic-x-video'
        elif ext in ['.htm', '.html']:
            ext = '.html'
        # if not: take icon 'unknown filetype'
        else:
            ext = 'unknown'

        # check if we have to do an image preview or not
        if preview_images and do_preview:
            image = make_thumbnail(request, formatter, get_url, ext)
        else:
            image = request.theme.make_icon(ext)

        parmdict['image'] = image
        parmdict['viewlink'] = viewlink
        parmdict['del_link'] = del_link

        parmdict['open_image'] = open_image
        
        action_args = 'do=get&amp;target=%(urlfile)s' % {'urlfile': urlfile, }
        url = '%(page_url)s?action=%(action)s&amp;%(action_args)s' % {
           'page_url': page_url,
           'action': action,
           'action_args': action_args, }
        text = ' %(image)s %(file)s ' % {'image': image, 'file': attachment, }
        getlink = wikiutil.link_tag(request, url, text=text,
                                    formatter=request.formatter)

        parmdict['getlink'] = getlink

        depth = len(attachment.split(os.path.sep)) - 1
        indent_txt = "<div class=indent%d>\n         " % depth

        if not os.path.isdir(os.path.join(base_dir, attachment).encode(config.charset)):
            data_5 = ('\n'
                      '         %(viewlink)s\n'
                      '         <a href="%(get_url)s"> %(label_get)s </a>\n'
                      '         %(del_link)s\n     ') % parmdict
            data_2 = '&nbsp;'
            if display_attach_syntax:
                if pagename == request.formatter.page.page_name:
                    data_2 = 'attachment:%(file)s' % {'file' : wikiutil.url_quote(attachment), }
                else:
                    data_2 = 'attachment:%(pagename)s/%(file)s' % { 
                       'file': wikiutil.url_quote(attachment),
                       'pagename': pagename, }

            html = html + _table_row( { 
                                      'data_1' : indent_txt + '<strong>%(getlink)s</strong>' % parmdict,
                                      'data_2' : data_2,
                                      'data_3' : '%(fsize)s&nbsp;KB' % parmdict,
                                      'data_4' : '%(fdate)s' % { 'fdate' : fdate },
                                      'data_5' : data_5,
                                    } )

    html = html + '\n</table>\n</div>\n'

    if display_table_closed:
        close_str = ('\n<script type="text/javascript">\n'
                     '<!--\nshowHideContents(%(file_id)s);\n-->\n'
                     '</script>\n' ) % { 'file_id' :  file_id, }
        html = html + close_str


    return html

def getArgs(given_arguments, allowed_arguments):
    if not given_arguments:
        return {}
    args = {}
    for s in given_arguments.split(','):
        if s and s.find('=') > 0:
            key, value = s.split('=', 1)
            if key and value:
                key = key.strip()
                if key in allowed_arguments:
                    args[key] = value.strip()
    return args

def execute(macro, options):
    arguments = ['page', 'preview', 'syntax', 'closed', 'readonly']
    args = getArgs(options, arguments)
    pagename = args.get('page', macro.formatter.page.page_name)

    # access directory
    attach_dir = getAttachDir(macro.request, pagename)

    default_table_closed = 0
    if hasattr(macro.request.cfg, 'attach_table_compact'):
        default_table_closed = macro.request.cfg.attach_table_compact
    table_closed = int(args.get('closed', default_table_closed))

    default_attach_syntax = 0
    display_attach_syntax = int(args.get('syntax', default_attach_syntax))
    
    table_readonly = int(args.get('readonly', 0))
    preview_images = int(args.get('preview', 0))

    return file_table(macro.formatter, macro.request, attach_dir, pagename,
                      preview_images, table_closed, display_attach_syntax, table_readonly)

