#!/usr/bin/env python
# encoding: utf-8
"""
@author: simin. Gong
@license: (C) Copyright 2013-2023 Spacemit Corporation Limited.
@contact: simin.gong@spacemit.com
@file: plugin.py
@date: 2024/12/4 19:31 
@desc:
"""
import base64
import os
import sys
import multiprocessing
import time
import cv2
from ai_tool.plugins.camera_detect import libs
from multiprocessing import Process
from .detect_node import DetectNode
from .usb_cam_node import UsbCamNode

lib_path = os.path.dirname(libs.__file__)

yolov8n_path = os.path.join(lib_path, 'yolov8n.q.onnx')
rtmpose_path = os.path.join(lib_path, 'rtmpose-t.sim.q.onnx')


class CameraDetectPlugin(Process):

    STOP_FLAG = '#%8899**'

    def __init__(self):
        super(CameraDetectPlugin, self).__init__(daemon=False)
        self.data_queue = multiprocessing.Queue()
        self.usb_cam = None
        self.daemon = True
        self.e_Event = multiprocessing.Event()
        self.start_time = 0
        self.frame_count = 0

    def get_date_queue(self):
        while True:
            data = self.data_queue.get()
            if data == self.STOP_FLAG:
                break
            yield data

    def run(self):
        sys.path.clear()
        sys.path.append(lib_path)
        self.run_camera_plugin()

    def run_camera_plugin(self):
        detect = DetectNode("dete0", yolov8n_path, self.data_callback)
        self.usb_cam = UsbCamNode("usbCam0", 1, self.data_callback)
        detect.attach_to([self.usb_cam])
        self.usb_cam.start()
        self.start_time = time.time()
        self.e_Event.wait()
        print(f'开始关闭进程 {os.getpid()}')
        self.usb_cam.stop_cap()
        print('相机关闭成功')
        self.usb_cam.detach_recursively()
        print('进程结束')

    def data_callback(self, frame, target):
        if frame is None:
            self.data_queue.put((frame, target))
            return
        ret, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 30])
        frame = base64.b64encode(buffer).decode('utf-8')
        self.data_queue.put((frame, target))

    def print_fps(self):
        current_time = time.time()
        self.frame_count +=1
        if current_time - self.start_time >= 1.0:
            fps = self.frame_count / (current_time - self.start_time)
            print(f"FPS: {fps:.2f}")
            self.frame_count = 0
            self.start_time = current_time

    def stop(self):
        self.data_queue.put(self.STOP_FLAG)
        self.e_Event.set()
        self.join(timeout=3)
        if self.is_alive():
            print("强制杀进程!")
            self.terminate()
        # kill_process_and_children(self.pid)
        print("进程结束成功!")


def kill_process_and_children(pid):
    """
    Kills a process and all of its children.

    Args:
        pid: The process ID of the parent process to kill.
    """
    import psutil
    try:
        parent = psutil.Process(pid)
        children = parent.children(recursive=True)
        for child in children:
            try:
                child.kill()
            except psutil.NoSuchProcess:
                pass  # Ignore if process already gone
        parent.kill()
    except psutil.NoSuchProcess:
        print(f"Process with PID {pid} not found.")
    except psutil.AccessDenied:
        print(f"Permission denied to kill process {pid}.  Run as root/administrator.")
    except Exception as e:
        print(f"An error occurred: {e}")
