'''

    Manipulation des formulaires PDF

@author: olivier.massot, sept. 2017
'''
import codecs
import subprocess

from path import Path


PDFTK_PATH = Path(__file__).parent.parent / r"bin\pdftk.exe"

def gen_xfdf(filename, datas={}):
    ''' Generates a temp XFDF file suited for fill_form function, based on dict input data '''

    fields = []
    for key, value in datas.items():
        fields.append("""<field name="%s"><value>%s</value></field>""" % (key, _normalize(value)))

    tpl = """<?xml version="1.0" encoding="UTF-8"?>
    <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
        <fields>
            %s
        </fields>
    </xfdf>""" % "\n\t\t\t".join(fields)

    filename = Path(filename)
    with open(filename, 'w') as f:
        f.write(tpl)

    convert_to_utf8(filename)

    return filename

def convert_to_utf8(filename):
    f = codecs.open(filename, 'r', 'cp1252', errors='ignore')
    u = f.read()  # now the contents have been transformed to a Unicode string
    out = codecs.open(filename, 'w', 'utf-8', errors='ignore')
    out.write(u)  # and now the contents have been output as UTF-8
    f.close()
    out.close()

def fill_form(pdfname, xfdfname, out_file, flatten=True):
    '''
        Fills a PDF form with given dict input data.
        Return temp file if no out_file provided.
    '''
    cmd = "%s %s fill_form %s output %s need_appearances" % (PDFTK_PATH, pdfname, xfdfname, out_file)
    if flatten:
        cmd += ' flatten'

    run_command(cmd, True)

    return out_file

def check_output(*popenargs, **kwargs):
    if 'stdout' in kwargs:
        raise ValueError('stdout argument not allowed, it will be overridden.')
    process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
    output, unused_err = process.communicate()
    retcode = process.poll()
    if retcode:
        cmd = kwargs.get("args")
        if cmd is None:
            cmd = popenargs[0]
        raise subprocess.CalledProcessError(retcode, cmd)
    return output

def _normalize(value):
    return str(value).replace("\"", "'").replace("<", "&lt;").replace(">", "&gt;")

def run_command(command, shell=False):
    ''' run a system command and yield output '''
    p = check_output(command, shell=shell)
    return str(p).split('\n')
