##############################################################################
#
# Copyright (c) 2007 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""RML to PDF Converter
"""
import os
import subprocess
import sys


_fileOpen = None


def excecuteSubProcess(xmlInputName, outputFileName, testing=None):
    # set the sys path given from the parent process
    sysPath = os.environ['Z3CRMLSYSPATH']
    sys.path[:] = sysPath.split(';')

    # now it come the ugly thing, but we need to hook our test changes into
    # our subprocess.
    if testing is not None:

        # set some globals
        import z3c.rml.attr
        import z3c.rml.directive
        global _fileOpen
        _fileOpen = z3c.rml.attr.File.open

        def testOpen(img, filename):
            # cleanup win paths like:
            # ....\\input\\file:///D:\\trunk\\...
            if sys.platform[:3].lower() == "win":
                if filename.startswith('file:///'):
                    filename = filename[len('file:///'):]
            path = os.path.join(os.path.dirname(xmlInputName), filename)
            return open(path, 'rb')
        # override some testing stuff for our tests
        z3c.rml.attr.File.open = testOpen
        import z3c.rml.tests.module
        sys.modules['module'] = z3c.rml.tests.module
        sys.modules['mymodule'] = z3c.rml.tests.module

    # import rml and process the pdf
    from z3c.rml import rml2pdf
    rml2pdf.go(xmlInputName, outputFileName)

    if testing is not None:
        # reset some globals
        z3c.rml.attr.File.open = _fileOpen
        del sys.modules['module']
        del sys.modules['mymodule']


def goSubProcess(xmlInputName, outputFileName, testing=False):
    """Processes PDF rendering in a sub process.

    This method is much slower then the ``go`` method defined in rml2pdf.py
    because each PDF generation is done in a sub process. But this will make
    sure, that we do not run into problems. Note, the ReportLab lib is not
    threadsafe.

    Use this method from python and it will dispatch the pdf generation
    to a subprocess.

    Note: this method does not take care on how much process will started.
    Probably it's a good idea to use a queue or a global utility which only
    start a predefined amount of sub processes.
    """
    # get the sys path used for this python process
    env = os.environ
    sysPath = ';'.join(sys.path)
    # set the sys path as env var for the new sub process
    env['Z3CRMLSYSPATH'] = sysPath
    py = sys.executable

    # setup the cmd
    program = [
        py,
        __file__,
        'excecuteSubProcess',
        xmlInputName,
        outputFileName]
    if testing is True:
        program.append('testing=1')
    program = " ".join(program)

    # run the subprocess in the rml input file folder, this will make it easy
    # to include images. If this doesn't fit, feel free to add a additional
    # home argument, and let this be the default, ri
    os.chdir(os.path.dirname(xmlInputName))

    # start processing in a sub process, raise exception or return None
    try:
        p = subprocess.Popen(program, executable=py, env=env,
                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    except Exception as e:
        raise Exception("Subprocess error: %s" % e)

    # Do we need to improve the implementation and kill the subprocess which
    # will fail? ri
    stdout, stderr = p.communicate()
    error = stderr
    if error:
        raise Exception("Subprocess error: %s" % error)


if __name__ == '__main__':
    if len(sys.argv) == 5:
        # testing support
        canvas = excecuteSubProcess(sys.argv[2], sys.argv[3], sys.argv[4])
    else:
        canvas = excecuteSubProcess(sys.argv[2], sys.argv[3])
