import urllib.request
from html.parser import HTMLParser
import xml.etree.ElementTree as ET
from xml.dom import minidom
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from urllib.parse import quote


# ==========================================
# NASTAVENIE
# ==========================================

START_DATE = datetime.now().date()

DAYS = 3

OUTPUT = "/opt/epg/sledovani.xml"

TIMEZONE = ZoneInfo("Europe/Bratislava")
TIMEZONE = ZoneInfo("Europe/Prague")


CHANNELS = [
    "animal_planet",
    "ard",
    "auto_motor_sport",
    "axn",
    "axnblack",
    "axnwhite",
    "baby_tv",
    "ballcasterz",
    "barrandov",
    "barrandovplus",
    "bbc",
    "bbc_earth",
    "bbc_first",
    "boomerang",
    "brno1",
    "btv",
    "cartoon_network_hd",
    "cinemax1",
    "cinemax2",
    "cms_tv",
    "cnn",
    "cs_film",
    "csrtv",
    "ct1",
    "ct1_sk",
    "ct1jm",
    "ct1jzc",
    "ct1sm",
    "ct1svc",
    "ct2",
    "ct24",
    "ct4sport",
    "ctart",
    "ctdecko",
    "dajto",
    "detskeradio",
    "Discovery",
    "Disney_Channel",
    "disney_junior",
    "DocuBoxHD",
    "dog_cat",
    "doma",
    "ducktv_cz",
    "duna",
    "dunaworld",
    "DVTV",
    "epic_drama",
    "espresso",
    "Eurosport",
    "Eurosport2",
    "fanda",
    "FashionboxHD",
    "fast_epg_comedy",
    "fast_epg_czsk",
    "fast_epg_family",
    "fast_epg_kids",
    "fast_epg_kids_sk",
    "fast_sledovanietv_comedy",
    "fast_sledovanietv_czsk",
    "fast_sledovanietv_family",
    "Fastnfunbox",
    "FightboxHD",
    "Film_Europe",
    "film_plus",
    "filmbox",
    "FilmboxArthouse",
    "FilmboxExtra",
    "FilmboxFamily",
    "FilmboxHD",
    "filmboxplus",
    "filmpro",
    "fireplace",
    "fishinghunting",
    "food_network",
    "france24",
    "france24_fr",
    "funbox_uhd",
    "godzone_tv",
    "golf",
    "GTTV",
    "haha_tv",
    "HBO",
    "hbo_comedy",
    "HBO2",
    "hgtv_ce",
    "history",
    "hn_tv",
    "hobby",
    "horor_film",
    "i_concerts",
    "ID",
    "ivodarenstvi",
    "ivysocina_stream_zs",
    "jihoceska_televize",
    "Jim_Jam",
    "joj",
    "joj_24",
    "joj_sport",
    "joj_sport2",
    "joj_svet",
    "joj_svet_cz",
    "jojcinema",
    "jojfamily",
    "jojplus",
    "Kino_CS",
    "kinobarrandov",
    "kinosvet",
    "kladno",
    "komentovana_krmeni",
    "krea_tv",
    "krusna_tv",
    "KVIFF_TV",
    "lala_tv",
    "levicka_tv",
    "locall_tv",
    "loop_naturetv_mumlava_waterfalls",
    "loop_naturetv-galerie-zvirat",
    "loop_naturetv-osetrovani-mladat",
    "love_nature",
    "m1",
    "m2",
    "m4",
    "m5",
    "markiza",
    "markiza_klasik",
    "markiza_krimi",
    "markizaint",
    "mezzo",
    "mezzo_live",
    "Minimax",
    "mnamtv",
    "mnau",
    "moldava_tv",
    "mtv",
    "nat_geo_wild",
    "naturetv",
    "NGC_HD",
    "nhk",
    "Nickelodeon",
    "nickjr",
    "nicktoons",
    "NoePlus",
    "nova",
    "nova_lady",
    "nova_sport",
    "nova_sport2",
    "novacinema",
    "novaint",
    "ocko",
    "ocko_blackHD",
    "ocko_expresHD",
    "ocko_express",
    "ocko_starHD",
    "ockogold",
    "ockoHD",
    "orf1",
    "orf2",
    "pan_kubinska_hora",
    "pan_marino_brdo",
    "plzen_tv",
    "pohoda",
    "Polar",
    "polsat",
    "polsatsport",
    "praha",
    "prima_krimi",
    "prima_krimi_sk",
    "prima_love_sk",
    "prima_max",
    "prima_news",
    "prima_show",
    "prima_sport",
    "prima_star",
    "primacool",
    "primacool_sk",
    "primafamily",
    "primalove",
    "primaplus",
    "primazoom",
    "pscr",
    "radior",
    "raj_tv",
    "rebel",
    "regiotv",
    "regiotv_hun",
    "retro",
    "rik",
    "rik2",
    "rt_jc",
    "rt_ustecko",
    "rtm_plus_liberec",
    "rusyn_fm",
    "ruzomberok",
    "rv_tv",
    "sat_crime_invest",
    "seejay",
    "senzi_tv",
    "severka_tv",
    "Seznam",
    "sky_news",
    "slagr",
    "slagr_premium",
    "slagr2",
    "slovacko",
    "slovak_sport",
    "slovak_sport2",
    "smichov",
    "spektrum",
    "spektrum_home",
    "sport1cz",
    "sport1sk",
    "Sport2",
    "stork_nest",
    "stork_nest_sk",
    "stv1",
    "stv1sk",
    "stv2",
    "stv24",
    "stv2sk",
    "stv4",
    "ta3",
    "telka",
    "tik_bohumin",
    "TLC",
    "travelhd",
    "travelxp",
    "tv_bratislava",
    "tv_central",
    "tv_doktor",
    "tv_liptov",
    "tv_lux",
    "tv_mistral",
    "tv_nitricka",
    "tv_nove_zamky",
    "tv_osem",
    "tv_paprika",
    "tv_partizanske",
    "tv_poprad",
    "tv_prerov",
    "tv_puls",
    "tv_reduta",
    "tv_romana",
    "tv_ruzinov",
    "tv_sen",
    "tv_slovensko",
    "tv5",
    "tv7",
    "tv9",
    "tvbeskyd",
    "TVlife",
    "tvnoe",
    "tvp1",
    "tvp2",
    "tvp3",
    "tvr",
    "uatv",
    "ukraina_24",
    "up_network",
    "uscenes_cat_cafe",
    "uscenes_coral_garden",
    "uscenes_hammock_beach",
    "uscenes_hammock_beach_hd",
    "ustecko_tv",
    "v1tv",
    "vega",
    "viasat_explore",
    "viasat_history",
    "viasat_nature",
    "war",
    "warner_tv",
    "wau",
    "zaktv",
    "zdf",
    "zoo_brno_a_vesnice",
    "zoo_brno_m_ledni",
    "zvirata_v_zoo"
]

# ==========================================
# HTML PARSER
# ==========================================

class EPGParser(HTMLParser):

    def __init__(self, channel_id):
        super().__init__()

        self.channel_id = channel_id

        self.programmes = []

        self.current_time = None
        self.current_title = None

        self.in_li = False
        self.in_a = False

    def handle_starttag(self, tag, attrs):

        attrs = dict(attrs)

        if tag == "li":

            self.in_li = True

            self.current_time = None
            self.current_title = None

        if self.in_li and tag == "span":

            data_time = attrs.get("data-time")

            if data_time:

                try:
                    self.current_time = int(data_time)
                except ValueError:
                    pass

        if self.in_li and tag == "a":

            href = attrs.get("href", "")

            if "channelEvent:" + self.channel_id + ":" in href:

                self.in_a = True

    def handle_data(self, data):

        if self.in_a:

            text = data.strip()

            if text:

                if self.current_title:

                    self.current_title += " " + text

                else:

                    self.current_title = text

    def handle_endtag(self, tag):

        if tag == "a":

            self.in_a = False

        if tag == "li":

            if self.current_time and self.current_title:

                self.programmes.append({
                    "start": self.current_time,
                    "title": self.current_title
                })

            self.in_li = False


# ==========================================
# XMLTV
# ==========================================

tv = ET.Element("tv")

tv.set(
    "generator-info-name",
    "SledovaniTV"
)


total_channels = 0
total_programmes = 0


# ==========================================
# CHANNELS
# ==========================================

for channel_id in CHANNELS:

    print()
    print("==========================================")
    print("KANÁL:")
    print("ID:", channel_id)
    print("==========================================")


    # --------------------------------------
    # CHANNEL
    # --------------------------------------

    channel = ET.SubElement(
        tv,
        "channel"
    )

    channel.set(
        "id",
        channel_id
    )

    display_name = ET.SubElement(
        channel,
        "display-name"
    )

    display_name.text = channel_id

    total_channels += 1


    # --------------------------------------
    # DNI
    # --------------------------------------

    base_urls = [
        "https://sledovanitv.cz/epg/default/",
        "https://sledovanietv.sk/epg/default/"
    ]

    for day_offset in range(DAYS):

        current_date = START_DATE + timedelta(
            days=day_offset
        )

        date_string = current_date.strftime(
            "%Y-%m-%d"
        )

        print()
        print("Dátum:", date_string)

        programmes = []

        # --------------------------------------
        # SKÚSENIE CZ / SK
        # --------------------------------------

        for base_url in base_urls:

            url = (
                base_url
                + date_string
                + "?channel=channel%3A"
                + quote(channel_id)
            )

            print("URL:", url)

            try:

                req = urllib.request.Request(
                    url,
                    headers={
                        "User-Agent": "Mozilla/5.0"
                    }
                )

                with urllib.request.urlopen(
                    req,
                    timeout=30
                ) as response:

                    html = response.read().decode(
                        "utf-8"
                    )

            except Exception as e:

                print("CHYBA:", e)

                continue


            parser = EPGParser(
                channel_id
            )

            parser.feed(html)

            test_programmes = parser.programmes


            # ----------------------------------
            # ODSTRÁNENIE DUPLÍC
            # ----------------------------------

            unique = {}

            for p in test_programmes:

                key = (
                    p["start"],
                    p["title"]
                )

                if key not in unique:

                    unique[key] = p


            test_programmes = list(
                unique.values()
            )


            test_programmes.sort(
                key=lambda x: x["start"]
            )


            print(
                "Nájdené programy:",
                len(test_programmes)
            )


            # ----------------------------------
            # AK SME NIEČO NAŠLI, POUŽIJEME TO
            # ----------------------------------

            if test_programmes:

                programmes = test_programmes

                break


        # --------------------------------------
        # PROGRAMMES
        # --------------------------------------

        for i, program in enumerate(
            programmes
        ):

            start_timestamp = program[
                "start"
            ]


            start_dt = datetime.fromtimestamp(
                start_timestamp,
                tz=TIMEZONE
            )


            # Koniec programu =
            # začiatok ďalšieho programu

            if i + 1 < len(programmes):

                end_timestamp = programmes[
                    i + 1
                ]["start"]

                end_dt = datetime.fromtimestamp(
                    end_timestamp,
                    tz=TIMEZONE
                )

            else:

                # Posledný program dňa
                # zatiaľ +1 hodina

                end_dt = (
                    start_dt
                    + timedelta(hours=1)
                )


            start_xml = start_dt.strftime(
                "%Y%m%d%H%M%S %z"
            )

            end_xml = end_dt.strftime(
                "%Y%m%d%H%M%S %z"
            )


            programme = ET.SubElement(
                tv,
                "programme"
            )

            programme.set(
                "start",
                start_xml
            )

            programme.set(
                "stop",
                end_xml
            )

            programme.set(
                "channel",
                channel_id
            )


            title = ET.SubElement(
                programme,
                "title"
            )

            title.set(
                "lang",
                "cs"
            )

            title.text = program[
                "title"
            ]


            total_programmes += 1

# ==========================================
# ULOŽENIE XML
# ==========================================

xml_data = ET.tostring(
    tv,
    encoding="utf-8"
)


pretty = minidom.parseString(
    xml_data
).toprettyxml(
    indent="    ",
    encoding="UTF-8"
)


with open(
    OUTPUT,
    "wb"
) as f:

    f.write(pretty)


# ==========================================
# VÝSLEDOK
# ==========================================

print()
print()
print("==========================================")
print(" SLEDOVANITV XMLTV – 3 DNI")
print("==========================================")
print("Od:       ", START_DATE)
print("Počet dní:", DAYS)
print("Kanály:   ", total_channels)
print("Programy: ", total_programmes)
print("Výstup:   ", OUTPUT)
print("==========================================")
print()

