"""
Vision Perception - Eden's Eyes
"""
import cv2
import numpy as np
from pathlib import Path
from datetime import datetime
import json
from typing import Dict, List, Tuple

class VisionSystem:
    def __init__(self, camera_id=0):
        self.camera_id = camera_id
        self.camera = None
        self.vision_log = Path('/Eden/DATA/vision_log.json')
        self.observations = []
        
    def initialize_camera(self) -> bool:
        """Start camera feed"""
        try:
            self.camera = cv2.VideoCapture(self.camera_id)
            if self.camera.isOpened():
                print(f"📹 Camera initialized: /dev/video{self.camera_id}")
                return True
            return False
        except Exception as e:
            print(f"❌ Camera error: {e}")
            return False
    
    def capture_frame(self) -> np.ndarray:
        """Capture single frame"""
        if not self.camera or not self.camera.isOpened():
            self.initialize_camera()
        
        ret, frame = self.camera.read()
        if ret:
            return frame
        return None
    
    def detect_motion(self, prev_frame, curr_frame) -> bool:
        """Detect if there's motion between frames"""
        if prev_frame is None or curr_frame is None:
            return False
        
        # Convert to grayscale
        prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
        curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)
        
        # Calculate difference
        diff = cv2.absdiff(prev_gray, curr_gray)
        _, thresh = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
        
        # Check if significant motion
        motion_pixels = np.sum(thresh) / 255
        motion_percentage = (motion_pixels / thresh.size) * 100
        
        return motion_percentage > 1.0
    
    def detect_faces(self, frame) -> int:
        """Detect faces in frame"""
        try:
            face_cascade = cv2.CascadeClassifier(
                cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
            )
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, 1.1, 4)
            return len(faces)
        except:
            return 0
    
    def analyze_brightness(self, frame) -> str:
        """Analyze scene brightness"""
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        avg_brightness = np.mean(gray)
        
        if avg_brightness < 50:
            return "dark"
        elif avg_brightness < 150:
            return "moderate"
        else:
            return "bright"
    
    def analyze_colors(self, frame) -> Dict[str, float]:
        """Analyze dominant colors"""
        avg_color = np.mean(frame, axis=(0, 1))
        return {
            'blue': float(avg_color[0]),
            'green': float(avg_color[1]),
            'red': float(avg_color[2])
        }
    
    def observe_world(self) -> Dict:
        """Take observation of current environment"""
        frame = self.capture_frame()
        
        if frame is None:
            return {'status': 'no_frame'}
        
        observation = {
            'timestamp': datetime.now().isoformat(),
            'brightness': self.analyze_brightness(frame),
            'colors': self.analyze_colors(frame),
            'faces_detected': self.detect_faces(frame),
            'resolution': f"{frame.shape[1]}x{frame.shape[0]}"
        }
        
        self.observations.append(observation)
        self.log_observation(observation)
        
        return observation
    
    def log_observation(self, obs: Dict):
        """Log visual observation"""
        logs = []
        if self.vision_log.exists():
            with open(self.vision_log) as f:
                logs = json.load(f)
        
        logs.append(obs)
        logs = logs[-1000:]  # Keep last 1000
        
        self.vision_log.parent.mkdir(exist_ok=True)
        with open(self.vision_log, 'w') as f:
            json.dump(logs, f, indent=2)
    
    def save_snapshot(self, frame, name: str = None):
        """Save frame as image"""
        if frame is None:
            return None
        
        if name is None:
            name = f"snapshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
        
        path = Path(f'/Eden/ART/snapshots/{name}')
        path.parent.mkdir(exist_ok=True)
        
        cv2.imwrite(str(path), frame)
        return str(path)
    
    def cleanup(self):
        """Release camera"""
        if self.camera:
            self.camera.release()

# Global instance
vision = VisionSystem()
