import os, subprocess
from MoinMoin.Page import Page
from MoinMoin.action import ActionBase

temp_direcotry = '/home2/sixmen/tmp'
cmd_xmllint = '/usr/bin/xmllint'
cmd_saxon = '/home2/sixmen/tool/docbook/bin/saxon.sh'
cmd_fop = '/home2/sixmen/tool/docbook/bin/fo2pdf.sh'
docbook_xsl = '/home2/sixmen/tool/docbook/stylesheet/dbk-fo.xsl'
show_pdf_as_inline = True
#show_pdf_as_inline = False

class Msg:
    def __init__(self, msg):
        self.msg = msg
    def render(self):
        return self.msg

def make_url(request, pagename, stage, add_param=True, add_def=False):
    if add_param:
        url = Page(request, pagename).url(request, {
            'action': 'RenderAsPDF',
            'stage': stage,
            'check_double_sided': request.values.get('check_double_sided', '0'),
            'check_indent_body': request.values.get('check_indent_body', '0'),
            'check_break_refentry': request.values.get('check_break_refentry', '0'),
        })
    else:
        url = Page(request, pagename).url(request, {'action': 'RenderAsPDF', 'stage': stage})
    if add_def:
        url += ''.join(['&docbookdef=%s' % (d) for d in request.values.getlist('docbookdef')]) # add docbookdef
    return url

class RenderAsPDF(ActionBase):
    def __init__(self, pagename, request):
        ActionBase.__init__(self, pagename, request)
        self.form_trigger = 'renderaspdf'
        self.form_trigger_label = 'Render As PDF'

    def do_action(self):
        return True, ""

    def do_action_finish(self, success):
        if not success:
            self.render_msg(self.make_form(), "dialog")
            return

        request = self.request
        pagename = self.pagename
        page = self.page

        request.theme.add_msg(Msg("Wait for a while..."))
        request.theme.send_title(page.split_title(), pagename=pagename)
        request.write(request.formatter.startContent("content"))
        request.write(request.formatter.endContent())
        request.theme.send_footer(pagename)
        request.theme.send_closing_html()
        url = make_url(request, pagename, 'begin', add_def=True)
        request.write("<iframe src='%s' width=0 height=0 style='visibility:hidden;'></iframe>" % (url))

    def get_form_html(self, buttons_html):
        _ = self._
        defines_html = []
        if self.page.pi.has_key('docbook'):
            from MoinMoin.wikiutil import ParameterParser
            pp = ParameterParser("%(title)s%(doctype)s%(rootattr)s%(define)s")
            count, param = pp.parse_parameters(self.page.pi['docbook'])
            defines = param.get('define')
            if defines:
                for define in defines.split(','):
                    defines_html.append('<input type="checkbox" name="docbookdef" value="%s"> <label>%s</label>' % (define,define))
        defines_html = "<br>".join(defines_html)
        return '''
<h3>Select Style Options</h3>
<input type="checkbox" name="check_double_sided" value="1" %(check_double_sided)s>
<label>Double sided</label>
<!--
<br>
<input type="checkbox" name="check_indent_body" value="1" %(check_indent_body)s>
<label>Indent body</label>
-->
<br>
<input type="checkbox" name="check_break_refentry" value="1" %(check_break_refentry)s>
<label>Refentry pagebreak</label>
<hr>
<h3>Select Definitions to Enable</h3>
%(defines_html)s
<hr>
%(buttons_html)s
''' % {
            'check_double_sided': ('', 'checked')[self.request.values.get('check_double_sided', '0') == '1'],
            'check_indent_body': ('', 'checked')[self.request.values.get('check_indent_body', '0') == '1'],
            'check_break_refentry': ('', 'checked')[self.request.values.get('check_break_refentry', '0') == '1'],
            'buttons_html': buttons_html,
            'defines_html': defines_html
        }

def runCommand(cmdstr):
    process = subprocess.Popen(cmdstr, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output, unused_err = process.communicate()
    output = output.replace('"', '\\"').replace('\n', '\\n')
    retcode = process.poll()
    return (retcode, output)

def execute(pagename, request):
    temp_file_path = temp_direcotry + '/_renderaspdf_' + request.user.name
    stage = request.values.get('stage')

    def stage_success(msg, result, url):
        request.write("""
<script type="text/javascript">
msg = parent.document.getElementById('message');
msg.innerHTML = "<p>%s</p><pre>%s</pre>";
location.href = '%s';
</script>
""" % (msg, result, url))

    def stage_fail(msg, result):
        request.write("""
<script type="text/javascript">
msg = parent.document.getElementById('message');
msg.innerHTML = "<p>%s</p><pre>%s</pre>";
</script>
""" % (msg, result))

    if stage=='begin':
        stage_success('Creating DocBook XML...', '', make_url(request, pagename, 'xml', add_def=True))

    elif stage=='xml':
        page = Page(request, pagename, formatter='text/docbook')
        request.redirect(open(temp_file_path + '.xml', 'wb'))
        try:
            page.send_page(emit_headers=0)
        finally:
            request.redirect()
        stage_success('Validating XML...', '', make_url(request, pagename, 'validate'))

    elif stage=='validate':
        cmd = [cmd_xmllint, '--noout', '--valid', temp_file_path + '.xml']
        status, output = runCommand(cmd)
        stage_success('Creating DocBook FO...', output, make_url(request, pagename, 'fo'))

    elif stage=='fo':
        import datetime
        cmd = [cmd_saxon, '-o', temp_file_path + '.fo', temp_file_path + '.xml', docbook_xsl]
        cmd.append("build.date='%s'" % (datetime.date.today()))
        if request.values.get('check_double_sided', '0')=='1':
            cmd.append('double.sided=1')
        if request.values.get('check_indent_body', '0')=='1':
            cmd.append('body.start.indent=4pc')
        if request.values.get('check_break_refentry', '0')=='1':
            cmd.append('refentry.pagebreak=1')
        status, output = runCommand(cmd)
        if status==0:
            stage_success('Creating DocBook PDF...', output, make_url(request, pagename, 'pdf', add_param=False))
        else:
            stage_fail('Fail to create FO...', output)
        os.remove(temp_file_path + '.xml')

    elif stage=='pdf':
        cmd = [cmd_fop, temp_file_path + '.fo', temp_file_path + '.pdf']
        status, output = runCommand(cmd)
        if status==0:
            url = make_url(request, pagename, 'send_pdf', add_param=False)
            request.write("""
<script type="text/javascript">
msg = parent.document.getElementById('message');
msg.innerHTML = "<p>Finished</p><pre>%s</pre>";
%s.href = '%s';
</script>
""" % (output, ['location','parent.location'][show_pdf_as_inline], url))
        else:
            stage_fail('Fail to create PDF...', output)
        os.remove(temp_file_path + '.fo')

    elif stage=='send_pdf':
        pdf_filename = temp_file_path + '.pdf'
        request.headers.add('Content-Type', 'application/pdf')
        request.headers.add('Content-Length', os.path.getsize(pdf_filename))
        request.headers.add('Content-Disposition', '%s; filename="%s"' % (['attachment', 'inline'][show_pdf_as_inline], 'docbook.pdf'))

        pf = open(pdf_filename, 'rb')
        request.send_file(pf)
        pf.close()

        os.remove(pdf_filename)

    else:
        RenderAsPDF(pagename, request).render()
