import os
import sys
import time
import requests
import subprocess
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QVBoxLayout, QListWidget, QWidget, QHBoxLayout,
    QListWidgetItem, QLabel, QSplitter, QFrame, QPushButton
)
from PyQt5.QtCore import Qt, QTimer, QEvent, QTime
import vlc

class VideoFrame(QFrame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet("background-color: black;")

class OverlayWindow(QWidget):
    def __init__(self, main_window):
        super().__init__(None)
        self.main_window = main_window
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
        self.setFocusPolicy(Qt.NoFocus)
        self.setMouseTracking(True)

        self.channel_label = QLabel("Channel Name", self)
        self.resolution_label = QLabel("Resolution", self)
        self.clock_label = QLabel("Clock", self)

        for label in [self.channel_label, self.resolution_label, self.clock_label]:
            label.setStyleSheet("color: white; background-color: rgba(0,0,0,160); padding: 4px; border-radius: 6px;")
            label.setFixedHeight(25)

        self.channel_label.move(10, 10)
        self.resolution_label.move(10, 45)
        self.clock_label.move(10, 80)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_clock)
        self.timer.start(1000)
        self.update_clock()

    def update_clock(self):
        current_time = QTime.currentTime().toString("HH:mm:ss")
        self.clock_label.setText(current_time)

    def update_info(self, name, resolution):
        self.channel_label.setText(name)
        self.resolution_label.setText(resolution)

    def mouseDoubleClickEvent(self, event):
        self.main_window.toggle_fullscreen()

class VLCPlayer:
    def __init__(self, video_frame):
        self.instance = vlc.Instance()
        self.media_player = self.instance.media_player_new()
        if sys.platform == "win32":
            self.media_player.set_hwnd(int(video_frame.winId()))
        else:
            self.media_player.set_xwindow(int(video_frame.winId()))

    def play_stream(self, url):
        if self.media_player.is_playing():
            self.media_player.stop()
            time.sleep(0.5)
        media = self.instance.media_new(url)
        media.add_option(":network-caching=3000")
        self.media_player.set_media(media)
        self.media_player.play()

    def stop(self):
        self.media_player.stop()

    def release(self):
        self.media_player.release()
        self.instance.release()

class IPTVWindow(QMainWindow):
    def __init__(self, php_dir):
        super().__init__()
        self.setWindowTitle("IPTV Player with EPG")
        self.setGeometry(100, 100, 1280, 720)
        self.php_dir = php_dir
        self._is_fullscreen = False
        self._normal_geometry = None
        self._normal_flags = None
        self.init_ui()
        self.installEventFilter(self)
        self.download_playlist()

    def init_ui(self):
        self.splitter = QSplitter(Qt.Horizontal)
        self.channel_list = QListWidget()
        self.channel_list.itemClicked.connect(self.on_channel_clicked)
        self.splitter.addWidget(self.channel_list)

        right_panel = QWidget()
        layout = QVBoxLayout(right_panel)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.video_container = QWidget()
        self.video_container.setStyleSheet("background-color: black;")
        self.video_container.setMinimumHeight(400)
        video_container_layout = QVBoxLayout(self.video_container)
        video_container_layout.setContentsMargins(0, 0, 0, 0)

        self.video_frame = VideoFrame(self.video_container)
        video_container_layout.addWidget(self.video_frame)

        layout.addWidget(self.video_container, stretch=3)

        self.player = VLCPlayer(self.video_frame)

        self.overlay_window = OverlayWindow(self)
        self.overlay_window.show()
        self.overlay_sync_timer = QTimer()
        self.overlay_sync_timer.timeout.connect(self.update_overlay_position)
        self.overlay_sync_timer.start(500)

        self.epg_display = QLabel("EPG info will appear here")
        self.epg_display.setStyleSheet("background-color: #222; color: white; padding: 10px;")
        layout.addWidget(self.epg_display, stretch=1)

        self.controls = QWidget()
        ctl_layout = QHBoxLayout(self.controls)
        for text, slot in [("⏮️", self.play_previous_channel),
                           ("⏯️", self.toggle_play_pause),
                           ("⏭️", self.play_next_channel),
                           ("🖵", self.toggle_fullscreen)]:
            btn = QPushButton(text)
            btn.clicked.connect(slot)
            ctl_layout.addWidget(btn)
        layout.addWidget(self.controls)

        self.splitter.addWidget(right_panel)
        self.splitter.setSizes([300, 980])
        self.setCentralWidget(self.splitter)

    def update_overlay_position(self):
        if not self.overlay_window or not self.video_frame:
            return
        vf_geom = self.video_frame.geometry()
        global_pos = self.video_frame.mapToGlobal(vf_geom.topLeft())
        self.overlay_window.setGeometry(global_pos.x(), global_pos.y(), vf_geom.width(), vf_geom.height())
        self.overlay_window.raise_()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.update_overlay_position()

    def eventFilter(self, source, event):
        if event.type() == QEvent.MouseButtonDblClick:
            self.toggle_fullscreen()
            return True
        return super().eventFilter(source, event)

    def on_channel_clicked(self, item: QListWidgetItem):
        url = item.data(Qt.UserRole)
        self.player.play_stream(url)

        def update(attempt=0):
            w = self.player.media_player.video_get_width()
            h = self.player.media_player.video_get_height()
            fps = self.player.media_player.get_fps()
            if w > 0 and h > 0:
                label = "SD"
                if w >= 3840:
                    label = "4K"
                elif w >= 1920:
                    label = "FHD"
                elif w >= 1280:
                    label = "HD"
                info = f"{label}, {fps:.2f}FPS"
                base = item.text().split('(')[0].strip()
                item.setText(f"{base} ({info})")
                self.overlay_window.update_info(base, info)
                QTimer.singleShot(100, self.update_overlay_position)
            elif attempt < 10:
                QTimer.singleShot(500, lambda: update(attempt+1))

        QTimer.singleShot(1000, lambda: update(0))

    def toggle_play_pause(self):
        mp = self.player.media_player
        if mp.is_playing():
            mp.pause()
        else:
            mp.play()

    def play_next_channel(self):
        idx = self.channel_list.currentRow()
        if idx < self.channel_list.count() - 1:
            self.channel_list.setCurrentRow(idx+1)
            self.on_channel_clicked(self.channel_list.currentItem())

    def play_previous_channel(self):
        idx = self.channel_list.currentRow()
        if idx > 0:
            self.channel_list.setCurrentRow(idx-1)
            self.on_channel_clicked(self.channel_list.currentItem())

    def toggle_fullscreen(self):
        if not self._is_fullscreen:
            self._normal_geometry = self.geometry()
            self._normal_flags = self.windowFlags()
            self.channel_list.hide()
            self.epg_display.hide()
            self.controls.hide()
            self.setWindowFlags(self._normal_flags | Qt.FramelessWindowHint)
            self.showFullScreen()
        else:
            self.setWindowFlags(self._normal_flags)
            self.showNormal()
            if self._normal_geometry:
                self.setGeometry(self._normal_geometry)
            self.channel_list.show()
            self.epg_display.show()
            self.controls.show()
        self._is_fullscreen = not self._is_fullscreen
        self.update_overlay_position()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape and self._is_fullscreen:
            self.toggle_fullscreen()
        else:
            super().keyPressEvent(event)

    def download_playlist(self):
        try:
            os.makedirs(self.php_dir, exist_ok=True)
            url = "https://iptv.nywebforum.com/playlist.m3u"
            content = requests.get(url, timeout=10).text.replace(
                "https://iptv.nywebforum.com", "http://localhost:8888"
            )
            path = os.path.join(self.php_dir, "playlist.m3u")
            with open(path, "w", encoding="utf-8") as f:
                f.write(content)
            self.load_playlist(path)
        except Exception as e:
            print(f"Failed to download playlist: {e}")

    def load_playlist(self, path):
        try:
            lines = open(path, encoding="utf-8").read().splitlines()
            self.channel_list.clear()
            first = None
            name = None
            for l in lines:
                if l.startswith("#EXTINF:"):
                    name = l.split(',')[-1].strip()
                elif l and not l.startswith("#") and name:
                    it = QListWidgetItem(f"{name} (Loading...)")
                    it.setData(Qt.UserRole, l)
                    self.channel_list.addItem(it)
                    if first is None:
                        first = it
                    name = None
            if first:
                self.channel_list.setCurrentItem(first)
                QTimer.singleShot(1000, lambda: self.on_channel_clicked(first))
        except Exception as e:
            print(f"Failed to load playlist: {e}")

def start_php_server(php_dir, port=8888):
    try:
        os.chdir(php_dir)
        return subprocess.Popen([
            "php", "-S", f"localhost:{port}"],
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
            creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0
        )
    except Exception:
        return None

if __name__ == "__main__":
    php_dir = os.path.join(os.path.dirname(__file__), "php_files")
    os.makedirs(php_dir, exist_ok=True)
    php_proc = start_php_server(php_dir)
    app = QApplication(sys.argv)
    window = IPTVWindow(php_dir)
    window.show()
    exit_code = app.exec_()
    window.player.stop()
    window.player.release()
    if php_proc:
        php_proc.terminate(); php_proc.wait(2)
    sys.exit(exit_code)