#!/usr/bin/env python3

import os
import subprocess
import sys

if len(sys.argv) != 2:
    print("usage: gen-cta-vic.py <CTA-861-H PDF>", file=sys.stderr)
    sys.exit(1)
in_path = sys.argv[1]
in_basename = os.path.basename(in_path)

tool_dir = os.path.dirname(os.path.realpath(__file__))
out_path = tool_dir + "/../cta-vic-table.c"

# Page numbers for CTA-861-H
pages = {
    "timing": (41, 43),
    "sync": (44, 46),
    "aspect_ratio": (55, 58),
}

def extract_pages(page_range):
    pages = []
    page = ""
    cmd = ["pdftotext", "-f", str(page_range[0]), "-l", str(page_range[1]), "-layout", in_path, "-"]
    for l in subprocess.check_output(cmd, text=True):
        if l.startswith("\f"):
            pages.append(page)
            page = l[1:]
        else:
            page += l
    return pages

def extract_table(page):
    lines = [l.strip() for l in page.splitlines()]
    rows = []
    for l in lines:
        fields = [field.strip() for field in l.split("  ") if field != ""]
        rows.append(fields)
    return rows

def parse_vic_list(s):
    return [int(vic.strip()) for vic in s.split(",")]

def parse_hactive(s):
    # Some hactive pixel values have a footnote marker
    if s == "14402" or s == "28802":
        s = s[:-1]
    return int(s)

def parse_interlaced(s):
    if s == "Prog":
        return "false"
    elif s == "Int":
        return "true"
    else:
        assert(False)

def parse_timing_table(page, format_table):
    assert("Table 1 - Video Format Timings — Detailed Timing Information" in page)

    for fields in extract_table(page):
        if len(fields) != 11 or fields[0] == "VIC":
            continue
        for vic in parse_vic_list(fields[0]):
            format_table[vic] = {
                "vic": vic,
                "h_active": parse_hactive(fields[1]),
                "v_active": int(fields[2]),
                "interlaced": parse_interlaced(fields[3]),
                "pixel_clock_hz": int(float(fields[10]) * 1000 * 1000),
            }

def parse_polarity(pol):
    if pol == "P":
        return "POSITIVE"
    elif pol == "N":
        return "NEGATIVE"
    else:
        assert(False)

def parse_sync_table(page, format_table):
    assert("Table 2 - Video Format Timings — Detailed Sync Information" in page)

    for fields in extract_table(page):
        if len(fields) < 12:
            continue
        for vic in parse_vic_list(fields[0]):
            fmt = format_table[vic]
            fmt["h_front"] = int(fields[2])
            fmt["h_sync"] = int(fields[3])
            fmt["h_back"] = int(fields[4])
            fmt["h_sync_polarity"] = "DI_CTA_VIDEO_FORMAT_SYNC_" + parse_polarity(fields[5])
            fmt["v_front"] = int(fields[6])
            fmt["v_sync"] = int(fields[7])
            fmt["v_back"] = int(fields[8])
            fmt["v_sync_polarity"] = "DI_CTA_VIDEO_FORMAT_SYNC_" + parse_polarity(fields[9])

def parse_aspect_ratio_table(page, format_table):
    assert("Table 3 - Video Formats — Video ID Code and Aspect Ratios" in page)

    for fields in extract_table(page):
        if len(fields) != 5:
            continue
        vic = int(fields[0])
        fmt = format_table[vic]
        pic_ar = fields[3]
        if pic_ar == "64:276":
            # 64:27 has a footnote
            pic_ar = pic_ar[:-1]
        fmt["picture_aspect_ratio"] = "DI_CTA_VIDEO_FORMAT_PICTURE_ASPECT_RATIO_" + pic_ar.replace(":", "_")

format_table = {}
for page in extract_pages(pages["timing"]):
    parse_timing_table(page, format_table)
for page in extract_pages(pages["sync"]):
    parse_sync_table(page, format_table)
for page in extract_pages(pages["aspect_ratio"]):
    parse_aspect_ratio_table(page, format_table)

max_vic = 0
for vic in format_table:
    if vic > max_vic:
        max_vic = vic

# Sanity check
for vic in format_table:
    fmt = format_table[vic]
    assert("h_sync" in fmt)
    assert("picture_aspect_ratio" in fmt)

with open(out_path, "w+") as f:
    f.write("/* DO NOT EDIT! This file has been generated by gen-cta-vic.py from {}. */\n\n".format(in_basename))
    f.write('#include "cta.h"\n\n')
    f.write("const struct di_cta_video_format _di_cta_video_formats[] = {\n")
    for vic in format_table:
        f.write("\t[{}] = {{\n".format(vic))
        for k, v in format_table[vic].items():
            f.write("\t\t.{} = {},\n".format(k, v))
        f.write("\t},\n")
    f.write("};\n\n")
    f.write("const size_t _di_cta_video_formats_len = {};\n".format(max_vic + 1))
