import re, subprocess, os

def dimensions_from_prolog(filename):
    mediabox_pat = re.compile(r"/MediaBox\s+\[(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\]", re.S)
    width_pat = re.compile(r"/Width\s+(\d+)", re.S)
    height_pat = re.compile(r"/Height\s+(\d+)", re.S)
    width = None
    height = None
    with open(filename, mode="rb") as fp:
        line = fp.readline().decode("ascii")
        while line:
            match = mediabox_pat.match(line)
            if match:
                x1, y1, x2, y2 = [int(e) for e in match.groups()]
                width = x2 - x1
                height = y2 - y1
            else:
                match = width_pat.match(line)
                if match:
                    width = int(match.group(1))
                else:
                    match = height_pat.match(line)
                    if match:
                        height = int(match.group(1))
            if width and height:
                break
            line = fp.readline().decode("ascii")
    return width, height


def dimensions_from_pdfinfo(filename):
    sp = subprocess.Popen(
        ["/usr/bin/pdfinfo", filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = sp.communicate()
    out = out.decode("ascii")
    width, height = None, None
    if out:
        pat = re.compile(r"Page size:\s+([\d.]+) x ([\d.]+) pts", re.S)
        match = pat.search(out)
        if match:
            width, height = [int(round(float(e))) for e in match.groups()]
    return width, height

# Doesn't agree with pdfinfo; why?
# from pdf2image import convert_from_path
# def dimensions_from_pdf2image(filename):
#     width, height = None, None
#     if pdf2image_imported:
#         img = convert_from_path(filename)[0]
#         width, height = img.size
#     return width, height


def dimensions(filename):
    width, height = None, None
    try:
        width, height = dimensions_from_prolog(filename)
    except:
        if width is None:
            width, height = dimensions_from_pdfinfo(filename)        
    if width is None:
        raise Exception(f'Could not determine the width and height of "{filename}"')        
    return width, height


def convert(pdf_filename, image_filename):
    if image_filename.endswith(".jpg"):
        arg1 = "-jpeg"
    elif image_filename.endswith(".png"):
        arg1 = "-png"
    else:
        raise Exception(f'PDF file "{pdf_filename}" can only be converted to PNG or JPEG')
    arg2 = "-singlefile"
    command = "/usr/bin/pdftoppm"
    basename = os.path.splitext(image_filename)[0]
    sp = subprocess.Popen(
        [command, arg1, arg2, pdf_filename, basename],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = sp.communicate()
    if err:
        raise Exception(f'Error creating image file from "{pdf_filename}": {err}')
