import cv2
import platform
import logging
import threading
from urllib.parse import urlparse
from ..utils import is_jetson, process_frame

_logger = logging.getLogger(__name__)

class GStreamerCapture:
    def __init__(self, rtsp_url, branches=None, cpu_arch=None, codec='h264', user=None, pw=None, need_user_pw=False):
        self.rtsp_url = rtsp_url
        self.cpu_arch = cpu_arch or platform.machine()
        
        # Check if GStreamer is supported in this OpenCV build
        gst_supported = any(b == cv2.CAP_GSTREAMER for b in cv2.videoio_registry.getBackends())
        
        self.codec = codec
        self.user = user
        self.pw = pw
        self.need_user_pw = need_user_pw or bool(user and pw)
        self.branches = branches or {}
        if self.branches:
            self.max_branch_w = max(int(b["WIDTH"]) for b in self.branches.values())
            self.max_branch_h = max(int(b["HEIGHT"]) for b in self.branches.values())
        else:
            self.max_branch_w = self.max_branch_h = None
            
        self.cap = cv2.VideoCapture()
        
    def open(self):
        # Match old version logic: Only use CAP_GSTREAMER if it's a pipeline string
        is_pipeline = self.rtsp_url.startswith('rtspsrc')
        
        if is_pipeline:
            target = lambda c, u, b: c.open(u, b)
            t = threading.Thread(target=target, args=(self.cap, self.rtsp_url, cv2.CAP_GSTREAMER), daemon=True)
        else:
            target = lambda c, u: c.open(u)
            t = threading.Thread(target=target, args=(self.cap, self.rtsp_url), daemon=True)
        
        t.start()
        t.join(15)
        res = self.cap.isOpened()
        if not res:
            print(f"[GStreamerCapture] Error: Failed to open capture for {self.rtsp_url}")
        return res

    def isOpened(self):
        return self.cap.isOpened()

    def get_branches(self):
        """Read one frame and process it into all branches."""
        ret, frame = self.cap.read()
        if not ret: return False, None
        
        frames_dict = {}
        for bid, bc in self.branches.items():
            frames_dict[bid] = process_frame(frame, bc, self.max_branch_w, self.max_branch_h)
        return True, frames_dict

    def read(self):
        """Standard read for backward compatibility."""
        return self.cap.read()

    def release(self):
        self.cap.release()

    def get(self, prop):
        return self.cap.get(prop)

    @staticmethod
    def build_pipeline(rtsp_url, cpu_arch, codec='h264', user=None, pw=None):
        if rtsp_url.startswith('rtspsrc'):
            return rtsp_url
        
        rtspsrc_params = [
            'short-header=true', 'is-live=true', 'protocols=tcp',
            'user-agent="LibVLC/3.0.18"', 'do-rtsp-keep-alive=true',
            'timeout=5000000', 'tcp-timeout=5000000'
        ]
        
        # Robust credential handling: if not provided, try to extract from URL
        if not user or not pw:
            try:
                parsed = urlparse(rtsp_url)
                if not user and parsed.username: user = parsed.username
                if not pw and parsed.password: pw = parsed.password
                
                # If credentials found in URL, clean the URL to use separate properties
                if parsed.username and parsed.password:
                    port = f":{parsed.port}" if parsed.port else ""
                    path = parsed.path if parsed.path else ""
                    query = f"?{parsed.query}" if parsed.query else ""
                    rtsp_url = f"rtsp://{parsed.hostname}{port}{path}{query}"
            except Exception:
                pass

        # Build rtspsrc location. Match old version: no quotes for location/user/pw
        rtspsrc = f'rtspsrc location={rtsp_url}'
        if user: rtspsrc += f' user-id={user}'
        if pw: rtspsrc += f' user-pw={pw}'
        rtspsrc += ' ' + ' '.join(rtspsrc_params)
        
        # Match old version decode chains exactly
        if cpu_arch == 'x86_64':
            decode_chain = [
                'queue max-size-buffers=0 max-size-bytes=1048576 leaky=downstream',
                'rtp{codec}depay', '{codec}parse', 'avdec_{codec}', 
                'videoconvert n-threads=1', 'appsink drop=true sync=false'
            ]
        elif cpu_arch == 'aarch64':
            if is_jetson():
                decode_chain = [
                    'queue max-size-buffers=0 max-size-bytes=1048576 leaky=downstream',
                    'rtp{codec}depay', '{codec}parse config-interval=1', 
                    'nvv4l2decoder', 'nvvidconv', 'queue max-size-buffers=1 leaky=downstream',
                    'video/x-raw,format=RGBA', 'videoconvert n-threads=1',
                    'video/x-raw,format=BGR', 'appsink drop=true sync=false'
                ]
            else:
                decode_chain = [
                    'rtp{codec}depay', '{codec}parse', 'avdec_{codec}', 
                    'videoconvert n-threads=1', 'appsink drop=true sync=false'
                ]
        else:
            decode_chain = [
                'rtp{codec}depay', '{codec}parse', 'avdec_{codec}', 
                'videoconvert n-threads=1', 'appsink drop=true sync=false'
            ]

        pipeline = ' ! '.join([rtspsrc] + decode_chain)
        return pipeline.format(codec=codec)
