"""
    MoinMoin - PDF Formatter

    @copyright: 2006 by Gerald Manipon

    @license: GNU GPL, see COPYING for details.
"""

import sys, traceback, os
import time, StringIO, codecs, shutil, re, errno
from tempfile import mkdtemp

from MoinMoin.formatter.base import FormatterBase
from MoinMoin import wikiutil, config
from MoinMoin.error import CompositeError
from MoinMoin.action import AttachFile
from MoinMoin.action.LocalSiteMap import PageTreeBuilder
from MoinMoin.Page import Page

url_prefix = "."
logo_html = '<img src="logo.png">'
HTML_SUFFIX = ".html"

page_template = u'''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=%(charset)s">
<title>%(pagename)s</title>
<link rel="stylesheet" type="text/css" media="all" charset="utf-8" href="%(theme)s/css/common.css">
<link rel="stylesheet" type="text/css" media="screen" charset="utf-8" href="%(theme)s/css/screen.css">
<link rel="stylesheet" type="text/css" media="print" charset="utf-8" href="%(theme)s/css/print.css">
</head>
<body>
<table>
<tr>
<td>
%(logo_html)s
</td>
</tr>
</table>
<div id="page">
<h1 id="title">%(pagename)s</h1>
%(pagehtml)s
</div>
</body>
</html>
'''

def _attachment(request, pagename, filename, outputdir):
    filename = filename.encode(config.charset)
    source_dir = AttachFile.getAttachDir(request, pagename)
    source_file = os.path.join(source_dir, filename)
    dest_dir = os.path.join(outputdir, "attachments", wikiutil.quoteWikinameFS(pagename))
    dest_file = os.path.join(dest_dir, filename)
    dest_url = "attachments/%s/%s" % (wikiutil.quoteWikinameFS(pagename), wikiutil.url_quote(filename))
    if os.access(source_file, os.R_OK):
        if not os.access(dest_dir, os.F_OK):
            try:
                os.makedirs(dest_dir)
            except:
                raise RuntimeError, "Cannot create attachment directory '%s'" % dest_dir
        elif not os.path.isdir(dest_dir):
            raise RuntimeError, "'%s' is not a directory" % dest_dir

        shutil.copyfile(source_file, dest_file)
        return dest_url
    else:
        return ""
  
def getPdf(request, pagename):

    # Prepare output directory
    outputdir = mkdtemp()
    try:
        os.mkdir(outputdir)
    except OSError, err:
        if err.errno != errno.EEXIST:
            raise RuntimeError, "Cannot create output directory '%s'!" % outputdir

    # Insert the current directory to the start of the path.
    sys.path.insert(0, os.path.abspath(os.curdir))

    # fix url_prefix so we get relative paths in output html
    request.cfg.url_prefix = url_prefix

    pages = PageMapper(pagename).getPages(request)

    wikiutil.quoteWikinameURL = lambda pagename, qfn=wikiutil.quoteWikinameFS: (qfn(pagename) + HTML_SUFFIX)

    AttachFile.getAttachUrl = lambda pagename, filename, request, addts=0, escaped=0: (_attachment(request, pagename, filename, outputdir))

    errfile = os.path.join(outputdir, 'error.log')
    errlog = open(errfile, 'w')
    errcnt = 0

    page_front_page = wikiutil.getSysPage(request, request.cfg.page_front_page).page_name
    page_title_index = wikiutil.getSysPage(request, 'TitleIndex').page_name
    page_word_index = wikiutil.getSysPage(request, 'WordIndex').page_name
    
    navibar_html = ''
    for p in [page_front_page, page_title_index, page_word_index]:
        navibar_html += '&nbsp;[<a href="%s">%s</a>]' % (wikiutil.quoteWikinameURL(p), wikiutil.escape(p))

    urlbase = request.url # save wiki base url
    newPages = []
    for pagename in pages:
        # we have the same name in URL and FS
        file = wikiutil.quoteWikinameURL(pagename) 
        newPages.append(file)
        try:
            pagehtml = ''
            request.url = urlbase + pagename # add current pagename to url base 
            page = Page(request, pagename)
            request.page = page
            try:
                request.reset()
                pagehtml = request.redirectedOutput(page.send_page, request, count_hit=0, content_only=1)
            except:
                errcnt = errcnt + 1
                print >>sys.stderr, "*** Caught exception while writing page!"
                print >>errlog, "~" * 78
                print >>errlog, file # page filename
                import traceback
                traceback.print_exc(None, errlog)
        finally:
            timestamp = time.strftime("%Y-%m-%d %H:%M")
            filepath = os.path.join(outputdir, file)
            fileout = codecs.open(filepath, 'w', config.charset)
            fileout.write(page_template % {
                'charset': config.charset,
                'pagename': wikiutil.unquoteWikiname(pagename),
                'pagehtml': pagehtml,
                'logo_html': logo_html,
                'navibar_html': navibar_html,
                'timestamp': timestamp,
                'theme': request.cfg.theme_default,
            })
            fileout.close()

    # copy FrontPage to "index.html"
    indexpage = pages[0] # index page has limited use when dumping specific pages, but create one anyway
    shutil.copyfile(
        os.path.join(outputdir, wikiutil.quoteWikinameFS(indexpage) + HTML_SUFFIX),
        os.path.join(outputdir, 'index' + HTML_SUFFIX)
    )

    errlog.close()
    if errcnt:
        print >>sys.stderr, "*** %d error(s) occurred, see '%s'!" % (errcnt, errfile)

    #write pdf and remove tempdir
    outputPdf = os.path.join(outputdir, '%s.pdf' % indexpage)
    htmlDocCmd = 'HTMLDOC_NOCGI=1 htmldoc --outfile %s %s > /dev/null 2>&1' % (outputPdf, ' '.join(["'%s/%s'" % (outputdir, i) for i in newPages]))
    os.environ['PATH'] = '%s:%s' % (os.path.join(sys.prefix,'bin'), os.environ['PATH'])
    os.system(htmlDocCmd)
    pdfVal = open(outputPdf).read()
    shutil.rmtree(outputdir)

    #return pdf content
    return pdfVal

class PageMapper:
    def __init__(self, name):
        self.name = name
        self.result = []

    def getPages(self, request):
        tree = PageTreeBuilder(request).build_tree(self.name)
        tree.depth_first_visit(request, self)
        return self.result

    def visit(self, request, name, depth):
        """ Visit a page, i.e. create a link.
        """
        if not name: return
        self.append(wikiutil.quoteWikinameURL(name))

    def append(self, text):
        self.result.append(text)

class Formatter(FormatterBase):

    def __init__(self, request, **kw):
        FormatterBase.__init__(self, request, **kw)

    def heading(self, *args, **kargs): return ""
    def paragraph(self, *args, **kargs): return ""
    def bullet_list(self, *args, **kargs): return ""
    def text(self, *args, **kargs): return ""
    def listitem(self, *args, **kargs): return ""
    def strong(self, *args, **kargs): return ""
    def code(self, *args, **kargs): return ""
    def attachment_image(self, *args, **kargs): return ""
    def sup(self, *args, **kargs): return ""
    def underline(self, *args, **kargs): return ""
    def emphasis(self, *args, **kargs): return ""
    def rule(self, *args, **kargs): return ""
    def table(self, *args, **kargs): return ""
    def table_row(self, *args, **kargs): return ""
    def table_cell(self, *args, **kargs): return ""
    def small(self, *args, **kargs): return ""
    def sub(self, *args, **kargs): return ""
    def linebreak(self, *args, **kargs): return ""
    def startDocument(self, pagename): return getPdf(self.request, pagename)
