import vlc
from fastapi import FastAPI
import asyncio
import csv
import time
from fastapi.middleware.cors import CORSMiddleware

# Create a local dictionary of channels from the csv file.
channels_dict = {}
STATIC_MODE = True   # UI-only mode

with open("all_channels.csv", "r") as file:
    reader = csv.reader(file)
    for eachLine in reader:
        if len(eachLine) == 0:
            continue
        ch_name = eachLine[0]
        ch_link = eachLine[1]
        channels_dict.update({ch_name: ch_link})


class AddChannel:
    channels_list = []

    def __init__(self, name):
        AddChannel.channels_list.append(self)
        self.name = name
        self.link = channels_dict.get(self.name)
        self.player = None  # 👈 critical

        print(f"New channel: {self.name}")

        if not STATIC_MODE:
            vlc_instance = vlc.Instance(
                "--no-audio --vout dummy --quiet "
                "--ts-csa2-ck=0000000000000000 "
                "--ts-csa-ck=0000000000000001"
            )
            self.player = vlc_instance.media_player_new()

            if self.link.startswith(("http", "https", "udp://")):
                self.player.set_mrl(self.link)

    def play(self):
        if self.player:
            self.player.play()

    def get_stats(self):
        return {
            "demux_bitrate": 0,
            "demux_corrupted": 0,
            "demux_discontinuity": 0,
            "demux_read_bytes": 0,
            "input_bitrate": 0,
            "read_bytes": 0,
            "time": 0,
            "drop_diff_1min": 0,
            "status": "Idle"
        }


# FastAPI Setup
app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Initialize channels
for ch_name, ch_link in channels_dict.items():
    print(ch_name, ch_link)
    AddChannel(name=ch_name)

channels_list = AddChannel.channels_list

print("-------------All Channels--------------")
print(channels_list)
print("---------------------------------------")


@app.on_event("startup")
def play():
    if not STATIC_MODE:
        for each_channel in channels_list:
            each_channel.play()


# If UDP streams exist, clear buffer periodically

@app.on_event("startup")
async def startup_event():
    contain_udp = False
    for each_channel in channels_list:
        if "udp://" in each_channel.name:
            contain_udp = True

    # if contain_udp:
    #     asyncio.create_task(clear_buffer())

    # asyncio.create_task(monitor_channels())  # new watchdog

# API: Get stats of all channels
@app.get("/stats")
def get_stats():
    return [[channel.name, channel.get_stats()] for channel in channels_list]


# API: Get stats of specific channel
@app.get("/stats/{channel_name}")
def get_specific_stats(channel_name: str):
    outputOBJ = None
    for channelOBJ in channels_list:
        if channelOBJ.name == channel_name:
            outputOBJ = channelOBJ

    if outputOBJ is None:
        return {
            "ERROR": f"The channel '{channel_name}' is not in the list. Please check your configuration."
        }

    return outputOBJ.name, outputOBJ.get_stats()


# Periodically clears VLC buffer to avoid memory bloat
async def clear_buffer():
    while True:
        print("_____Clearing the buffer______")
        for channelOBJ in channels_list:
            channel_stats = channelOBJ.get_stats()
            channel_buffer = channel_stats["read_bytes"]
            if channel_buffer > 100:
                channelOBJ.player.stop()
                channelOBJ.player.play()
                print("Buffer of {0} has been cleared".format(str(channelOBJ.name)))
        await asyncio.sleep(5)


async def monitor_channels():
    while True:
        for channelOBJ in channels_list:
            stats = channelOBJ.get_stats()
            demux_bitrate = stats["demux_bitrate"]

            # Check VLC state
            state = channelOBJ.player.get_state()

            # If VLC not in good state → restart
            if state not in (vlc.State.Playing, vlc.State.Buffering):
                print(f"[RESTART] {channelOBJ.name} bad state: {state}")
                channelOBJ.player.stop()
                await asyncio.sleep(1)
                channelOBJ.player.play()
                continue  # skip rest of checks this round

            # If demux_bitrate is 0 → stalled → restart
            if demux_bitrate == 0:
                print(f"[RESTART] {channelOBJ.name} stalled (demux_bitrate=0)")
                channelOBJ.player.stop()
                await asyncio.sleep(1)
                channelOBJ.player.play()

        await asyncio.sleep(30)  # check every 10s
