#pageflow.py
"""Support for using PageCatcher within Platypus"""
__all__ = ('LoadPdfFlowable', 'ShowPdfFlowable', 'loadPdf',
            )
import os
from reportlab.platypus.flowables import Flowable
from rlextra.pageCatcher.pageCatcher import copyPages, \
    storeFormsInMemory, restoreFormsInMemory, restoreFormsFromDict
from reportlab.pdfbase.pdfdoc import xObjectName

class LoadPdfFlowable(Flowable):
    """Imports PDF content into the current canvas when drawn.

    Used by RML2PDF, which has to store the forms itself but defer
    placing them into a document"""
    def __init__(self, pickledStuff, isDict=False, iptrans=None):
        Flowable.__init__(self)
        self.pickledStuff = pickledStuff
        self._isDict = isDict
        self._iptrans = iptrans

    def drawOn(self, canvas, x, y, _sW=0):
        "This makes sure the form XObjects are loaded into the canvas"
        iptrans = self._iptrans
        dor = iptrans and not iptrans.trivial()
        if dor:
            canvas.saveState()
            if not iptrans.noRotate():
                canvas.rotate(iptrans.degrees)
            if not iptrans.noTranslate():
                canvas.translate(iptrans.dx,iptrans.dy)
            if not iptrans.noScale():
                canvas.scale(iptrans.sx,iptrans.sy)
        (self._isDict and restoreFormsFromDict or restoreFormsInMemory)(self.pickledStuff,
                             canvas,
                             allowDuplicates=1)
        if dor:
            canvas.restoreState()

def _formName2ExtraInfo(canv,name):
    doc = canv._doc
    internalname = xObjectName(name)
    if internalname in doc.idToObject:
        form = doc.idToObject[internalname]
        if hasattr(form,'_extra_pageCatcher_info'):
            return form._extra_pageCatcher_info

def _formName2OrientationMatrix(canv,name,orientation):
    xi = _formName2ExtraInfo(canv,name)
    if xi:
        po = xi.get('Rotate',0)
        x0,y0,x1,y1 = xi['MediaBox']
        if orientation=='auto':
            orientation=po
        orientation = int(orientation % 360)
        if orientation==0:
            if not x0 and not y0: return
            matrix = [1,0,0,1,-x0,-y0]
        elif orientation==90:
            matrix = [0,-1,1,0,-y0,x1-x0]
        elif orientation==180:
            matrix = [-1,0,0,-1,x1-x0,y1-y0]
        else:
            matrix = [0,1,-1,0,y1-y0,-x0]
        return matrix

class ShowPdfFlowable(Flowable):
    "draws a form xobject in absolute coordinates"
    def __init__(self, formName,orientation=None,iptrans=None):
        Flowable.__init__(self)
        self.formName = formName
        self._orientation = orientation
        self._iptrans = iptrans

    def drawOn(self, canvas, x, y, _sW=0):
        iptrans = self._iptrans
        matrix = self._orientation
        dor = matrix or (iptrans and not iptrans.trivial())
        if dor:
            canvas.saveState()
            if matrix:
                matrix = _formName2OrientationMatrix(canvas,self.formName,matrix)
                if matrix:
                    canvas.transform(*matrix)
            if iptrans:
                if not iptrans.noRotate():
                    canvas.rotate(iptrans.degrees)
                if not iptrans.noTranslate():
                    canvas.translate(iptrans.dx,iptrans.dy)
                if not iptrans.noScale():
                    canvas.scale(iptrans.sx,iptrans.sy)
        #this won't do much if already loaded
        canvas.doForm(self.formName)
        if dor:
            canvas.restoreState()

def loadPdf(filename, canvas, pageNumbers=None, prefix=None):
    if pageNumbers:
        all=0
    else:
        all=1
    if prefix is None:
        prefix = os.path.splitext(filename)[0] + '_page'
    prefix = prefix.replace('/','_')
    pdfContent = open(filename,"rb").read()
    (formNames, stuff) = storeFormsInMemory(pdfContent,
                                            pagenumbers=pageNumbers,
                                            prefix=prefix,
                                            all=1)

    if pageNumbers:
        namesToInclude = []
        for num in pageNumbers:
            namesToInclude.append(formNames[num])
    else:
        namesToInclude = None
    print('loaded %d pages in %d bytes:' % (len(formNames), len(stuff)))
    restoreFormsInMemory(stuff, canvas,
                         allowDuplicates=1,
                         verbose=1,
                         formnames=namesToInclude)
    return formNames

def test():
    #check for chaos on repeated use
    import reportlab.rl_config
    reportlab.rl_config.invariant = 1

    from reportlab.pdfgen.canvas import Canvas
    c = Canvas('pageflow1.pdf')
    loadPdf("test/ir684.pdf", c)
    c.setFont("Helvetica", 36)
    c.drawString(100,700, "Test restore forms")
    c.showPage()
    c.doForm("test_ir684_page0")
    c.showPage()
    c.doForm("test_ir684_page1")
    c.save()
    print('saved pageflow1.pdf')
    print('\n'*5)

    c = Canvas('pageflow2.pdf')
    loadPdf("test/ir684.pdf", c)
    loadPdf("test/ir684.pdf", c)
    c.setFont("Helvetica", 36)
    c.drawString(100,700, "Test restore forms")
    c.showPage()
    c.doForm("test_ir684_page0")
    c.showPage()
    c.doForm("test_ir684_page1")
    c.save()
    print('saved pageflow2.pdf')

    print('\n'*5)
    c = Canvas('pageflow3.pdf')
    loadPdf("test/ir684.pdf", c, pageNumbers=[0])
    loadPdf("test/ir684.pdf", c, pageNumbers=[1])
    c.setFont("Helvetica", 36)
    c.drawString(100,700, "Test restore forms")
    c.showPage()
    c.doForm("test_ir684_page0")
    c.showPage()
    c.doForm("test_ir684_page1")
    c.save()
    print('saved pageflow3.pdf')

if __name__=='__main__':
    test()
