import xbmc
import xbmcaddon
import os
import sys
import shutil
import uuid
import subprocess

ADDON = xbmcaddon.Addon()

_pip_running = False
_ffmpeg_proc = None
_imagefile = ''
_winHdl = None
_imgHdl = None
_lblNameHdl = None
_lblNbrHdl = None


class FfmpegProcess:
    def __init__(self):
        self.proc = None
        self.urlold = ''
        self.flgStarted = False
        self.ffmpeg_bin = 'C:\\ffmpeg\\bin\\ffmpeg.exe'
        self.imagefile = ''
        self._fps = 10
        self._width = 480
        self._load_settings()
    
    def _load_settings(self):
        profile_path = ADDON.getAddonInfo('profile')
        cache_base = os.path.join(profile_path, '..', 'cache')
        self._tmpfolder = os.path.join(cache_base, 'pip')
        if not os.path.exists(self._tmpfolder):
            try:
                os.makedirs(self._tmpfolder)
            except Exception:
                self._tmpfolder = os.path.join(profile_path, 'cache', 'pip')
                if not os.path.exists(self._tmpfolder):
                    try:
                        os.makedirs(self._tmpfolder)
                    except Exception:
                        self._tmpfolder = os.environ.get('TEMP', '.')
        
        self.imagefile = os.path.join(self._tmpfolder, 'pip_thumb.png')
    
    def start(self, url, seek_seconds=0, headers=None):
        if not url:
            return
        
        self.stop()
        
        url_lower = url.lower()
        is_live = '.m3u8' in url_lower or 'hls' in url_lower
        
        cmd = [self.ffmpeg_bin, '-nostdin']
        
        if not is_live:
            cmd += ['-reconnect', '1', '-reconnect_at_eof', '1', '-reconnect_streamed', '1', '-reconnect_delay_max', '5']
        
        if headers and '|' in url:
            import urllib.parse
            parts = url.split('|', 1)
            clean_url = parts[0].strip()
            header_string = parts[1].strip()
            
            parsed_headers = {}
            try:
                for pair in header_string.split('&'):
                    if '=' in pair:
                        key, val = pair.split('=', 1)
                        parsed_headers[key.strip()] = urllib.parse.unquote_plus(val.strip())
            except Exception:
                pass
            
            if parsed_headers:
                header_line = ''.join('%s: %s\r\n' % (k, v) for k, v in parsed_headers.items())
                cmd += ['-headers', header_line]
                url = clean_url
        
        cmd += ['-re', '-i', url]
        cmd += ['-an', '-vf', 'fps=%d,scale=%d:-1' % (self._fps, self._width), '-qscale:v', '5', '-f', 'image2', '-y', '-update', '1', '-vcodec', 'mjpeg', self.imagefile]
        
        try:
            self.proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, creationflags=subprocess.CREATE_NO_WINDOW)
            self.flgStarted = True
            self.urlold = url
        except (FileNotFoundError, PermissionError, OSError):
            self.flgStarted = False
    
    def stop(self):
        self.urlold = ''
        if self.proc:
            try:
                self.proc.kill()
                self.proc.wait()
            except Exception:
                pass
        self.proc = None
        if os.path.exists(self.imagefile):
            try:
                os.remove(self.imagefile)
            except Exception:
                pass
        self.flgStarted = False
    
    def started(self):
        return self.flgStarted
    
    def running(self):
        if self.proc is None:
            return False
        try:
            return self.proc.poll() is None
        except AttributeError:
            return False


def create_pip_overlay(channel_name=''):
    global _winHdl, _imgHdl, _lblNameHdl, _lblNbrHdl
    
    try:
        _winHdl = xbmcgui.Window(12005)
        wait_img = os.path.join(ADDON.getAddonInfo('path'), 'resources', 'data', 'wait4pip.png')
        shutil.copy(wait_img, _imagefile)
        
        _imgHdl = xbmcgui.ControlImage(30, 30, 480, 270, _imagefile)
        _winHdl.addControl(_imgHdl)
        
        _lblNameHdl = xbmcgui.ControlLabel(35, 300, 470, 40, channel_name or '', font='font10')
        _winHdl.addControl(_lblNameHdl)
        
        _lblNbrHdl = xbmcgui.ControlLabel(35, 35, 80, 40, '', font='font10')
        _winHdl.addControl(_lblNbrHdl)
    except Exception as e:
        xbmc.log('[jet_guide-pip] Failed to create overlay: %s' % str(e), xbmc.LOGERROR)


def update_pip_overlay():
    global _winHdl, _imgHdl, _lblNameHdl, _lblNbrHdl
    
    if not _imgHdl or not _winHdl:
        return
    
    if not os.path.exists(_imagefile):
        return
    
    try:
        old_uuid = _imagefile.replace('.png', '_uuid.png')
        new_uuid = _imagefile.replace('.png', '%s.png' % str(uuid.uuid4()))
        shutil.copy(_imagefile, new_uuid)
        _imgHdl.setImage(new_uuid, useCache=False)
        if os.path.exists(old_uuid):
            os.remove(old_uuid)
    except Exception as e:
        pass


def start_pip_service(channel_name=''):
    global _pip_running, _ffmpeg_proc, _imagefile
    
    _ffmpeg_proc = FfmpegProcess()
    _imagefile = _ffmpeg_proc.imagefile
    
    player = xbmc.Player()
    if not player.isPlaying():
        return False
    
    url = player.getPlayingFile()
    if not url:
        return False
    
    display_name = channel_name or player.getPlayingItem().getLabel()
    
    create_pip_overlay(display_name)
    
    _ffmpeg_proc.start(url, headers={'User-Agent': 'Kodi/21.2'})
    
    if not _ffmpeg_proc.started():
        return False
    
    _pip_running = True
    
    # Update loop - runs on main thread with Monitor.waitForAbort
    monitor = xbmc.Monitor()
    while _pip_running and _ffmpeg_proc.started():
        if monitor.waitForAbort(0.1):
            break
        update_pip_overlay()
    
    stop_pip_service()
    return True


def stop_pip_service():
    global _pip_running, _winHdl, _imgHdl, _lblNameHdl, _lblNbrHdl
    
    _pip_running = False
    
    if _ffmpeg_proc:
        _ffmpeg_proc.stop()
    
    if _imgHdl and _winHdl:
        try:
            _winHdl.removeControl(_imgHdl)
        except Exception:
            pass
    if _lblNameHdl and _winHdl:
        try:
            _winHdl.removeControl(_lblNameHdl)
        except Exception:
            pass
    if _lblNbrHdl and _winHdl:
        try:
            _winHdl.removeControl(_lblNbrHdl)
        except Exception:
            pass


def is_pip_running():
    return _pip_running


if __name__ == '__main__':
    # Service entry point - keep service alive
    monitor = xbmc.Monitor()
    while not monitor.abortRequested():
        xbmc.sleep(1)
