import os
import subprocess
from tempfile import NamedTemporaryFile

__version__ = '0.1'


def execute_wk(*args):
    """
    Generate path for the wkhtmltopdf binary and execute command.

    :param args: args to pass straight to subprocess.Popen
    :return: stdout, stderr
    """
    this_dir = os.path.dirname(__file__)
    on_heroku = 'DYNO' in os.environ
    wk_name = 'wkhtmltopdf-heroku' if on_heroku else 'wkhtmltopdf'
    wkhtmltopdf_default = os.path.join(this_dir, '../bin/', wk_name)
    # Reference command
    wkhtmltopdf_cmd = os.environ.get('WKHTMLTOPDF_CMD', wkhtmltopdf_default)
    if not os.path.isfile(wkhtmltopdf_cmd):
        raise IOError('wkhtmltopdf binary not found at %s' % wkhtmltopdf_cmd)
    wk_args = (wkhtmltopdf_cmd,) + args
    p = subprocess.Popen(wk_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    # it seems wkhtmltopdf's error codes can be false, we'll ignore them if we
    # seem to have generated a pdf
    if p.returncode != 0 and stdout[:4] != '%PDF':
        raise IOError('error running wkhtmltopdf, command: %r\nresponse: "%s"' % \
            (wk_args, stderr.strip(' \n')))
    return stdout, stderr


def generate_pdf(source,
                 quiet=True,
                 grayscale=False,
                 lowquality=False,
                 margin_bottom=None,
                 margin_left=None,
                 margin_right=None,
                 margin_top=None,
                 orientation=None,
                 page_height=None,
                 page_width=None,
                 page_size=None,
                 image_dpi=None,
                 image_quality=None,
                 **extra_kwargs):
    """
    Generate a pdf from either a url or a html string.

    After the html and url arguments all other arguments are
    passed straight to wkhtmltopdf

    For details on extra arguments see the output of get_help()
    and get_extended_help()

    All arguments whether specified or caught with extra_kwargs are converted
    to command line args with "'--' + original_name.replace('_', '-')"

    Arguments which are True are passed with no value eg. just --quiet, False
    and None arguments are missed, everything else is passed with str(value).

    :param source: html string to generate pdf from or url to get
    :param quiet: bool
    :param grayscale: bool
    :param lowquality: bool
    :param margin_bottom: string eg. 10mm
    :param margin_left: string eg. 10mm
    :param margin_right: string eg. 10mm
    :param margin_top: string eg. 10mm
    :param orientation: Portrait or Landscape
    :param page_height: string eg. 10mm
    :param page_width: string eg. 10mm
    :param page_size: string: A4, Letter, etc.
    :param image_dpi: int default 600
    :param image_quality: int default 94
    :param extra_kwargs: any exotic extra options for wkhtmltopdf
    :return: string representing pdf
    """
    is_url = any(source.strip().startswith(s) for s in ('http', 'www'))

    loc = locals()
    py_args = {n: loc[n] for n in
               ['quiet', 'grayscale', 'lowquality', 'margin_bottom', 'margin_left', 'margin_right', 'margin_top',
               'orientation', 'page_height', 'page_width', 'page_size', 'image_dpi', 'image_quality']}
    py_args.update(extra_kwargs)
    cmd_args = []
    for name, value in py_args.items():
        if value in [None, False]:
            continue
        arg_name = '--' + name.replace('_', '-')
        if value is True:
            cmd_args.append(arg_name)
        else:
            cmd_args.extend([arg_name, str(value)])

    def gen(src):
        with NamedTemporaryFile(suffix='.pdf', mode='rwb+') as pdf_file:
            execute_wk(*(cmd_args + [src, pdf_file.name]))
            pdf_file.seek(0)
            return pdf_file.read()

    if is_url:
        return gen(source)

    with NamedTemporaryFile(suffix='.html', mode='w') as html_file:
        html_file.write(source.encode('utf-8'))
        html_file.flush()
        html_file.seek(0)
        return gen(html_file.name)


def get_version():
    """
    Get version of pydf and wkhtmltopdf binary

    :return: version string
    """
    v = 'pydf version: %s\n' % __version__
    v += 'wkhtmltopdf version: %s' % execute_wk('-V')[0]
    return v


def get_help():
    """
    get help string from wkhtmltopdf binary
    uses -h command line option

    :return: help string
    """
    return execute_wk('-h')[0]


def get_extended_help():
    """
    get extended help string from wkhtmltopdf binary
    uses -H command line option

    :return: extended help string
    """
    return execute_wk('-H')[0]
@@ -881,300 +881,8 @@
     
-# it seems wkhtmltopdf's error codes can be false, we'll ignore them if we%0A    # seem to have generated a pdf%0A    if p.returncode != 0 and stdout%5B:4%5D != '%25PDF':%0A        raise IOError('error running wkhtmltopdf, command: %25r%5Cnresponse: %22%25s%22' %25 %5C%0A            (wk_args, stderr.strip(' %5Cn')))%0A    
 retu
@@ -898,16 +898,30 @@
 , stderr
+, p.returncode
 %0A%0A%0Adef g
@@ -3335,12 +3335,26 @@
  gen
-(src
+_pdf(src, cmd_args
 ):%0A 
@@ -3441,21 +3441,8 @@
     
-execute_wk(*(
 cmd_
@@ -3447,16 +3447,17 @@
 d_args +
+=
  %5Bsrc, p
@@ -3473,74 +3473,501 @@
 ame%5D
-))%0A            pdf_file.seek(0)%0A            return pdf_file.read()
+%0A            _, stderr, returncode = execute_wk(*cmd_args)%0A            pdf_file.seek(0)%0A            pdf_string = pdf_file.read()%0A            # it seems wkhtmltopdf's error codes can be false, we'll ignore them if we%0A            # seem to have generated a pdf%0A            if returncode != 0 and pdf_string%5B:4%5D != '%25PDF':%0A                raise IOError('error running wkhtmltopdf, command: %25r%5Cnresponse: %22%25s%22' %25 %5C%0A                    (cmd_args, stderr.strip(' %5Cn')))%0A            return pdf_string
 %0A%0A  
@@ -3997,23 +3997,37 @@
 turn gen
+_pdf
 (source
+, cmd_args
 )%0A%0A    w
@@ -4207,16 +4207,20 @@
 turn gen
+_pdf
 (html_fi
@@ -4226,16 +4226,26 @@
 ile.name
+, cmd_args
 )%0A%0A%0Adef 

move error checking to generate_pdf