#!/usr/bin/env python3

import gzip
import sys
import xml.etree.ElementTree as ET
from pathlib import Path

OUTPUT = Path("/srv/iptv/guide.xml.gz")

# Highest priority first.
SOURCES = [
    Path("/srv/containers/tvheadend/config/.xmltv/schedulesdirect.xml"),

    Path("/srv/iptv/epg/plutotvepg.xml"),
    Path("/srv/iptv/epg/webgrabplus/guide.xml"),

    Path("/srv/iptv/epg/iptv-org/guide-africa.xml"),
    Path("/srv/iptv/epg/iptv-org/guide-asia.xml"),
    Path("/srv/iptv/epg/iptv-org/guide-europe.xml"),
    Path("/srv/iptv/epg/iptv-org/guide-north-america.xml"),
    Path("/srv/iptv/epg/iptv-org/guide-oceania.xml"),
    Path("/srv/iptv/epg/iptv-org/guide-south-america.xml"),
]


def open_xml(path):
    if path.suffix == ".gz":
        return gzip.open(path, "rb")
    return open(path, "rb")


def valid_source(path):
    return path.exists() and path.stat().st_size > 100


sources = [p for p in SOURCES if valid_source(p)]

tmp = OUTPUT.with_suffix(".xml.gz.tmp")

seen_channels = set()
seen_programmes = set()

channel_count = 0
programme_count = 0

with gzip.open(tmp, "wb", compresslevel=6) as out:
    out.write(
        b'<?xml version="1.0" encoding="UTF-8"?>\n'
        b'<tv generator-info-name="Flamethrower82 Unified EPG">\n'
    )

    # First pass: channels.
    for path in sources:
        print(f"Channels: {path}", file=sys.stderr)

        with open_xml(path) as fh:
            for event, elem in ET.iterparse(fh, events=("end",)):
                if elem.tag == "channel":
                    cid = elem.attrib.get("id")

                    if cid and cid not in seen_channels:
                        seen_channels.add(cid)
                        out.write(ET.tostring(elem, encoding="utf-8"))
                        out.write(b"\n")
                        channel_count += 1

                elem.clear()

    # Second pass: programmes.
    #
    # Processing sources in priority order means the first programme for
    # channel+start wins. Schedules Direct therefore overrides lower-priority
    # sources automatically.
    for path in sources:
        print(f"Programmes: {path}", file=sys.stderr)

        with open_xml(path) as fh:
            for event, elem in ET.iterparse(fh, events=("end",)):
                if elem.tag == "programme":
                    channel = elem.attrib.get("channel")
                    start = elem.attrib.get("start")

                    if channel and start:
                        key = (channel, start)

                        if key not in seen_programmes:
                            seen_programmes.add(key)
                            out.write(ET.tostring(elem, encoding="utf-8"))
                            out.write(b"\n")
                            programme_count += 1

                elem.clear()

    out.write(b"</tv>\n")

tmp.replace(OUTPUT)

print(f"Channels:   {channel_count}", file=sys.stderr)
print(f"Programmes: {programme_count}", file=sys.stderr)
print(f"Output:     {OUTPUT}", file=sys.stderr)
