"""Command-line interface for ASCII Camera."""

import argparse
import os
import sys
import signal
from typing import Optional
import shutil

from .core import ASCIIConverter
from .camera import CameraCapture, FrameRateController
from .config import CharacterSet, ColorTheme, Config


class ASCIICameraApp:
    """Main ASCII Camera application."""
    
    def __init__(self, config: Config):
        """Initialize the application with configuration."""
        self.config = config
        self.converter = ASCIIConverter(
            charset=config.charset,
            color_theme=config.color_theme,
            invert=config.invert
        )
        self.camera: Optional[CameraCapture] = None
        self.frame_controller = FrameRateController(config.fps)
        self.running = False
        
    def setup_signal_handlers(self) -> None:
        """Setup signal handlers for graceful shutdown."""
        def signal_handler(signum, frame):
            print("\n\n🎬 ASCII Camera shutting down...")
            self.stop()
            sys.exit(0)
            
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)
    
    def clear_screen(self) -> None:
        """Clear the terminal screen."""
        os.system('cls' if os.name == 'nt' else 'clear')
    
    def get_terminal_size(self) -> tuple[int, int]:
        """Get current terminal size."""
        try:
            size = shutil.get_terminal_size()
            # Reserve some space for UI elements
            width = min(size.columns - 2, self.config.max_width or size.columns)
            height = min(size.lines - 4, self.config.max_height or size.lines)
            return width, height
        except:
            return 80, 24  # Fallback
    
    def print_header(self) -> None:
        """Print application header."""
        header = """
╔══════════════════════════════════════════╗
║            🎥 ASCII CAMERA 📹            ║
║        Real-time Retro Video Art         ║
╚══════════════════════════════════════════╝
Press Ctrl+C to exit
"""
        print(header)
    
    def run(self) -> int:
        """Run the main application loop."""
        self.setup_signal_handlers()
        
        try:
            # Initialize camera
            self.camera = CameraCapture(self.config.camera_index)
            
            if not self.camera.open():
                print(f"❌ Error: Could not open camera {self.config.camera_index}")
                print("💡 Try:")
                print("   - Check if camera is connected")
                print("   - Try different camera index: --camera 1")
                print("   - Close other applications using the camera")
                return 1
            
            # Print camera info
            cam_info = self.camera.get_camera_info()
            print(f"📷 Camera opened: {cam_info.get('width', 'unknown')}x{cam_info.get('height', 'unknown')} @ {cam_info.get('fps', 'unknown')} FPS")
            print(f"🎭 ASCII Mode: {self.config.charset.name.title()}")
            if self.config.color_theme:
                print(f"🌈 Color Theme: {self.config.color_theme.name.title()}")
            
            input("\nPress Enter to start...")
            
            self.running = True
            frame_count = 0
            
            while self.running:
                # Read frame
                frame = self.camera.read_frame()
                if frame is None:
                    print("❌ Failed to read camera frame")
                    break
                
                # Get current terminal size
                width, height = self.get_terminal_size()
                
                # Convert to ASCII
                ascii_art = self.converter.frame_to_ascii(frame, width, height)
                
                # Display
                self.clear_screen()
                self.print_header()
                print(ascii_art)
                
                # Frame rate control
                self.frame_controller.wait()
                frame_count += 1
                
        except KeyboardInterrupt:
            print("\n\n🎬 ASCII Camera stopped by user")
            
        except Exception as e:
            print(f"\n❌ Unexpected error: {e}")
            return 1
            
        finally:
            self.stop()
            
        print(f"📊 Total frames processed: {frame_count}")
        return 0
    
    def stop(self) -> None:
        """Stop the application and cleanup resources."""
        self.running = False
        if self.camera:
            self.camera.close()


def create_parser() -> argparse.ArgumentParser:
    """Create command-line argument parser."""
    parser = argparse.ArgumentParser(
        prog="ascii-camera",
        description="🎥 Real-time webcam to ASCII art converter",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  ascii-camera                        # Basic usage
  ascii-camera --color --theme matrix # Matrix-style colored output
  ascii-camera --charset detailed     # High detail ASCII
  ascii-camera --fps 8 --camera 1     # Slower FPS, second camera
        
Character Sets:
  simple   : ' .:-=+*#%@' (10 levels)
  detailed : ' .,'~!;<>+*xvXGM#8@' (16 levels) 
  block    : ' ░▒▓█' (4 levels, bold look)
        
Color Themes:
  matrix   : Classic green terminal
  amber    : Retro amber terminal  
  cyan     : Cool cyan blue
  rainbow  : Dynamic rainbow colors
        """
    )
    
    # Display options
    parser.add_argument(
        "--width", "-w",
        type=int,
        help="Maximum ASCII art width (default: auto-detect terminal)"
    )
    
    parser.add_argument(
        "--height", "-h", 
        type=int,
        help="Maximum ASCII art height (default: auto-detect terminal)"
    )
    
    parser.add_argument(
        "--fps",
        type=float,
        default=12.0,
        help="Target frames per second (default: 12)"
    )
    
    # ASCII options
    parser.add_argument(
        "--charset",
        type=str,
        choices=["simple", "detailed", "block"],
        default="simple",
        help="ASCII character set (default: simple)"
    )
    
    parser.add_argument(
        "--invert",
        action="store_true",
        help="Invert brightness mapping"
    )
    
    # Color options  
    parser.add_argument(
        "--color",
        action="store_true",
        help="Enable colored output"
    )
    
    parser.add_argument(
        "--theme",
        type=str,
        choices=["matrix", "amber", "cyan", "rainbow"],
        help="Color theme (requires --color)"
    )
    
    # Camera options
    parser.add_argument(
        "--camera",
        type=int,
        default=0,
        help="Camera device index (default: 0)"
    )
    
    # Info
    parser.add_argument(
        "--version",
        action="version",
        version="%(prog)s 1.0.0"
    )
    
    return parser


def main() -> int:
    """Main entry point."""
    parser = create_parser()
    args = parser.parse_args()
    
    # Convert string arguments to enums
    charset_map = {
        "simple": CharacterSet.SIMPLE,
        "detailed": CharacterSet.DETAILED, 
        "block": CharacterSet.BLOCK,
    }
    
    theme_map = {
        "matrix": ColorTheme.MATRIX,
        "amber": ColorTheme.AMBER,
        "cyan": ColorTheme.CYAN,
        "rainbow": ColorTheme.RAINBOW,
    }
    
    # Create configuration
    config = Config(
        charset=charset_map[args.charset],
        color_theme=theme_map.get(args.theme) if args.color and args.theme else None,
        fps=args.fps,
        camera_index=args.camera,
        max_width=args.width,
        max_height=args.height,
        invert=args.invert
    )
    
    # Run application
    app = ASCIICameraApp(config)
    return app.run()


if __name__ == "__main__":
    sys.exit(main())
