import cv2
import tkinter as tk
from tkinter import Canvas
from PIL import Image, ImageTk
import threading
import numpy as np
from config import config_manager

class PreviewWindow:
    """采集卡预览窗口"""
    def __init__(self):
        self.config = config_manager.config
        self.caps = {}
        self.frames = {}
        self.large_window = None
        self.running = True
        
    def init_cameras(self):
        """初始化所有相机"""
        for i, group in enumerate(self.config['groups']):
            if group.get('active', True):  # 只加载活动的配置
                try:
                    cap = cv2.VideoCapture(group['camera_index'], cv2.CAP_DSHOW)
                    if cap.isOpened():
                        cap.set(cv2.CAP_PROP_FRAME_WIDTH, group['camera_width'])
                        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, group['camera_height'])
                        self.caps[i] = {
                            'cap': cap,
                            'group': group,
                            'name': group['name']
                        }
                except Exception as e:
                    print(f"无法打开相机 {group['camera_index']}: {e}")
    
    def capture_frames(self):
        """捕获帧"""
        while self.running:
            for idx, data in self.caps.items():
                ret, frame = data['cap'].read()
                if ret:
                    # 裁剪到配置的区域
                    height, width = frame.shape[:2]
                    crop_top = 30
                    crop_bottom = min(crop_top + 720, height)
                    crop_width = min(1280, width)
                    frame = frame[crop_top:crop_bottom, 0:crop_width]
                    
                    # 转换颜色空间
                    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    self.frames[idx] = frame_rgb
    
    def create_grid_window(self):
        """创建网格窗口"""
        root = tk.Tk()
        root.title("采集卡预览 - 点击放大")
        root.geometry("1000x700")
        
        # 获取显示配置
        display = self.config.get('display', {})
        preview_width = display.get('preview_width', 640)
        preview_height = display.get('preview_height', 360)
        columns = display.get('preview_columns', 2)
        rows = display.get('preview_rows', 2)
        
        canvas = Canvas(root, bg='black')
        canvas.pack(fill=tk.BOTH, expand=True)
        
        # 存储图像对象
        self.photo_objects = {}
        
        def update_frames_once():
            """在主线程中更新一帧（使用after循环）"""
            if not self.running:
                return
            try:
                canvas.delete("all")

                # 计算每个预览窗口的位置和大小
                window_width = root.winfo_width() if root.winfo_width() > 1 else 1000
                window_height = root.winfo_height() if root.winfo_height() > 1 else 700

                cell_width = window_width // columns
                cell_height = window_height // rows

                frame_idx = 0
                for idx in self.caps.keys():
                    if idx in self.frames:
                        row = frame_idx // columns
                        col = frame_idx % columns

                        x = col * cell_width
                        y = row * cell_height

                        # 调整图像大小
                        frame = self.frames[idx]
                        h, w = frame.shape[:2]
                        scale = min(cell_width / w, cell_height / h) * 0.9
                        new_w = int(w * scale)
                        new_h = int(h * scale)

                        resized_frame = cv2.resize(frame, (new_w, new_h))

                        # 转换为PIL图像
                        pil_image = Image.fromarray(resized_frame)
                        photo = ImageTk.PhotoImage(image=pil_image)
                        # 保持引用，避免被GC
                        self.photo_objects[idx] = photo

                        # 绘制图像
                        center_x = x + cell_width // 2
                        center_y = y + cell_height // 2
                        canvas.create_image(center_x, center_y, image=photo, anchor='center')

                        # 绘制标签
                        name = self.caps[idx]['name']
                        canvas.create_text(center_x, y + 20, text=name, fill='white', font=('Arial', 12, 'bold'))

                        frame_idx += 1
            except Exception as e:
                print(f"更新帧错误: {e}")
            # 约30fps
            root.after(33, update_frames_once)
        
        def on_canvas_click(event):
            """点击画布事件"""
            window_width = root.winfo_width()
            window_height = root.winfo_height()
            cell_width = window_width // columns
            cell_height = window_height // rows
            
            col = int(event.x // cell_width)
            row = int(event.y // cell_height)
            index = row * columns + col
            
            # 找到对应的配置
            if index < len(self.caps):
                idx = list(self.caps.keys())[index]
                self.show_large_window(idx)
        
        canvas.bind('<Button-1>', on_canvas_click)
        
        # 使用after在主线程中循环刷新
        root.after(33, update_frames_once)
        
        def on_closing():
            """关闭窗口"""
            self.running = False
            for data in self.caps.values():
                data['cap'].release()
            root.destroy()
        
        root.protocol("WM_DELETE_WINDOW", on_closing)
        root.mainloop()
    
    def show_large_window(self, idx):
        """显示大窗口"""
        if self.large_window is not None and self.large_window.winfo_exists():
            self.large_window.destroy()
        
        self.large_window = tk.Toplevel()
        self.large_window.title(f"放大视图 - {self.caps[idx]['name']}")
        self.large_window.geometry("1280x720")
        
        canvas = Canvas(self.large_window, bg='black')
        canvas.pack(fill=tk.BOTH, expand=True)
        
        photo_obj = {}
        
        def update_large_once():
            if not self.running or not self.large_window.winfo_exists():
                return
            try:
                if idx in self.frames:
                    canvas.delete("all")

                    frame = self.frames[idx]
                    h, w = frame.shape[:2]

                    # 调整到窗口大小
                    window_width = self.large_window.winfo_width() if self.large_window.winfo_width() > 1 else 1280
                    window_height = self.large_window.winfo_height() if self.large_window.winfo_height() > 1 else 720

                    scale = min(window_width / w, window_height / h)
                    new_w = int(w * scale)
                    new_h = int(h * scale)

                    resized_frame = cv2.resize(frame, (new_w, new_h))
                    pil_image = Image.fromarray(resized_frame)
                    photo = ImageTk.PhotoImage(image=pil_image)
                    photo_obj['img'] = photo

                    canvas.create_image(window_width // 2, window_height // 2, image=photo, anchor='center')
            except Exception as e:
                print(f"更新大窗口错误: {e}")
            self.large_window.after(33, update_large_once)

        self.large_window.after(33, update_large_once)
    
    def run(self):
        """运行预览"""
        self.init_cameras()
        
        # 启动捕获线程
        capture_thread = threading.Thread(target=self.capture_frames, daemon=True)
        capture_thread.start()
        
        # 创建并显示网格窗口
        import time
        time.sleep(0.5)  # 等待几帧
        self.create_grid_window()

if __name__ == "__main__":
    preview = PreviewWindow()
    preview.run()

