import cv2
import numpy as np
from typing import List, Tuple, Optional

class TemporalTracker:
    def __init__(self, diff_threshold: float = 0.05):
        self.diff_threshold = diff_threshold
        self.last_frame = None
        self.current_page_frames = []
        self.unique_pages = []
        self.frame_count = 0
        self.stable_frame_count = 0

    def _extract_print_channel(self, bgr: np.ndarray) -> np.ndarray:
        # 흑백으로 변환하여 악보의 선, 숫자 등 고정 텍스트 기호 영역 픽셀을 명확히 함
        gray = np.max(bgr, axis=2)
        _, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY)
        return binary

    def process_frame(self, frame: np.ndarray, tracking_channel: Optional[np.ndarray] = None) -> None:
        if tracking_channel is not None:
            frame_gray = tracking_channel.copy()
        else:
            frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            
        self.frame_count += 1
        
        if self.last_frame is None:
            self.last_frame = frame_gray.copy()
            self.current_page_frames.append(frame.copy())
            self.stable_frame_count = 1
            return
            
        diff = cv2.absdiff(self.last_frame, frame_gray)
        _, thresh = cv2.threshold(diff, 50, 255, cv2.THRESH_BINARY)
        
        # 커서 이동 vs 페이지 전환을 명확히 구분하기 위한 혁신적 지표 도입
        # 커서는 세로로 길기 때문에 픽셀 면적(area)으로는 비중이 크지만 가로 폭(column)으로는 매우 좁음(전체 폭의 <5%).
        # 반면 실제 페이지 전환은 가로 전체에 걸쳐 악보가 바뀌므로(>15%).
        col_sums = np.sum(thresh > 0, axis=0)
        h, w = thresh.shape
        # 한 열에서 높이의 3% 이상 픽셀이 변한 경우 "유의미하게 변한 열"로 간주
        changed_cols = np.sum(col_sums > (h * 0.03)) 
        diff_ratio = changed_cols / w
        
        if diff_ratio > 0.15:  # 가로폭의 15% 이상이 완전히 바뀌면 페이지 전환
            self.stable_frame_count = 0
            if len(self.current_page_frames) > 0:
                print(f"[Tracker] Page Flip Detected! (Col Change: {diff_ratio*100:.1f}%) -> Saving Median Page {len(self.unique_pages)+1}")
                median_page = np.median(self.current_page_frames, axis=0).astype(np.uint8)
                self.unique_pages.append(median_page)
                self.current_page_frames = []
                
            self.last_frame = frame_gray.copy()
        else:
            self.stable_frame_count += 1
            if self.stable_frame_count % 3 == 0:
                self.current_page_frames.append(frame.copy())

    def get_final_panorama(self) -> Optional[np.ndarray]:
        # 시스템 호환성을 위해 이름만 panorama 유지 (실제로는 불필요해진 로직)
        return None
        
    def get_unique_pages(self) -> List[np.ndarray]:
        if len(self.current_page_frames) > 0:
            median_page = np.median(self.current_page_frames, axis=0).astype(np.uint8)
            self.unique_pages.append(median_page)
            print(f"[Tracker] Saving Final Median Page {len(self.unique_pages)}")
        return self.unique_pages
