#!/usr/bin/env python3

import sys
import os
from PIL import Image
import requests
from io import BytesIO


def get_terminal_size():
    """Get terminal size in columns and rows"""
    try:
        columns, rows = os.get_terminal_size()
        return columns, rows
    except (OSError, AttributeError):
        return 80, 24  # Default fallback


def resize_image(image, max_width=None, max_height=None):
    """Resize image to fit terminal while maintaining aspect ratio"""
    if max_width is None or max_height is None:
        cols, rows = get_terminal_size()
        max_width = max_width or cols
        max_height = max_height or (rows - 2) * 2  # Unicode blocks are 2:1 ratio

    # Calculate scaling factor
    width, height = image.size
    scale = min(max_width / width, max_height / height)

    # Resize image
    new_width = int(width * scale)
    new_height = int(height * scale)

    # Ensure even height for half-block characters
    if new_height % 2 != 0:
        new_height -= 1

    return image.resize((new_width, new_height), Image.Resampling.LANCZOS)


def rgb_to_ansi(r, g, b, background=False):
    """Convert RGB to ANSI escape code"""
    if background:
        return f"\033[48;2;{r};{g};{b}m"
    else:
        return f"\033[38;2;{r};{g};{b}m"


def get_image_as_unicode_blocks(image_path, max_width=None, max_height=None, with_ansi=True):
    """
    Convert image to Unicode half-blocks (▄) for double vertical resolution
    Returns list of strings - with or without ANSI codes
    """
    # Load image
    if image_path.startswith("http"):
        # Handle URL
        response = requests.get(image_path)
        img = Image.open(BytesIO(response.content))
    else:
        # Handle local file
        img = Image.open(image_path)

    # Convert to RGB if necessary
    if img.mode != "RGB":
        img = img.convert("RGB")

    # Resize image
    img = resize_image(img, max_width, max_height)
    width, height = img.size

    pixels = img.load()

    # Process image using half-blocks for better resolution
    output = []
    for y in range(0, height, 2):  # Process 2 rows at a time
        row = ""
        for x in range(width):
            # Get top pixel
            if y < height:
                r1, g1, b1 = pixels[x, y]
            else:
                r1, g1, b1 = 0, 0, 0

            # Get bottom pixel
            if y + 1 < height:
                r2, g2, b2 = pixels[x, y + 1]
            else:
                r2, g2, b2 = 0, 0, 0

            if with_ansi:
                # Use lower half block with top color as foreground and bottom as background
                row += rgb_to_ansi(r2, g2, b2, background=False)  # Bottom pixel (foreground)
                row += rgb_to_ansi(r1, g1, b1, background=True)  # Top pixel (background)
                row += "▄"  # Lower half block character
            else:
                # Just use a simple character based on brightness for curses
                avg_brightness = (r1 + g1 + b1 + r2 + g2 + b2) // 6
                if avg_brightness > 200:
                    row += "█"
                elif avg_brightness > 150:
                    row += "▓"
                elif avg_brightness > 100:
                    row += "▒"
                elif avg_brightness > 50:
                    row += "░"
                else:
                    row += " "

        if with_ansi:
            row += "\033[0m"  # Reset colors
        output.append(row)

    return output


def get_image_as_ascii_art(image_path, max_width=None, max_height=None):
    """
    Convert image to simple ASCII art for curses compatibility
    Returns list of simple ASCII strings without color codes
    """
    # ASCII characters from dark to light
    ascii_chars = " .:-=+*#%@"

    # Load image
    if image_path.startswith("http"):
        # Handle URL
        response = requests.get(image_path)
        img = Image.open(BytesIO(response.content))
    else:
        # Handle local file
        img = Image.open(image_path)

    # Convert to grayscale
    img = img.convert("L")

    # Resize image
    if max_height:
        max_height = max_height // 2  # Characters are roughly 2:1 ratio
    img = resize_image(img, max_width, max_height)
    width, height = img.size

    pixels = img.load()

    # Process image
    output = []
    for y in range(height):
        row = ""
        for x in range(width):
            brightness = pixels[x, y]
            # Map brightness to ASCII character
            char_index = int((brightness / 255) * (len(ascii_chars) - 1))
            row += ascii_chars[char_index]
        output.append(row)

    return output


def display_image_unicode_blocks(image_path, max_width=None, max_height=None):
    """
    Display image using Unicode half-blocks (▄) for double vertical resolution
    Each character position shows two pixels vertically
    """
    output = get_image_as_unicode_blocks(image_path, max_width, max_height)
    print("\n".join(output))


def display_image_full_blocks(image_path, max_width=None, max_height=None):
    """
    Display image using full blocks (█) - simpler but lower resolution
    Each character position shows one pixel
    """
    # Load image
    if image_path.startswith("http"):
        # Handle URL
        response = requests.get(image_path)
        img = Image.open(BytesIO(response.content))
    else:
        # Handle local file
        img = Image.open(image_path)

    # Convert to RGB if necessary
    if img.mode != "RGB":
        img = img.convert("RGB")

    # Resize image (account for character aspect ratio)
    if max_height:
        max_height = max_height // 2  # Characters are roughly 2:1 ratio
    img = resize_image(img, max_width, max_height)
    width, height = img.size

    pixels = img.load()

    # Process image
    output = []
    for y in range(height):
        row = ""
        for x in range(width):
            r, g, b = pixels[x, y]
            row += rgb_to_ansi(r, g, b, background=False)
            row += "█"  # Full block character

        row += "\033[0m"  # Reset colors
        output.append(row)

    # Print the image
    print("\n".join(output))


def display_image_quarters(image_path, max_width=None, max_height=None):
    """
    Display image using quarter blocks for 2x2 pixel resolution per character
    Uses Unicode quadrant characters for maximum resolution
    """
    # Quadrant block characters
    BLOCKS = {
        (0, 0, 0, 0): " ",
        (1, 0, 0, 0): "▘",
        (0, 1, 0, 0): "▝",
        (1, 1, 0, 0): "▀",
        (0, 0, 1, 0): "▖",
        (1, 0, 1, 0): "▌",
        (0, 1, 1, 0): "▞",
        (1, 1, 1, 0): "▛",
        (0, 0, 0, 1): "▗",
        (1, 0, 0, 1): "▚",
        (0, 1, 0, 1): "▐",
        (1, 1, 0, 1): "▜",
        (0, 0, 1, 1): "▄",
        (1, 0, 1, 1): "▙",
        (0, 1, 1, 1): "▟",
        (1, 1, 1, 1): "█",
    }

    # Load image
    if image_path.startswith("http"):
        response = requests.get(image_path)
        img = Image.open(BytesIO(response.content))
    else:
        img = Image.open(image_path)

    # Convert to RGB
    if img.mode != "RGB":
        img = img.convert("RGB")

    # Resize image (each character represents 2x2 pixels)
    if max_width:
        max_width *= 2
    if max_height:
        max_height *= 2

    img = resize_image(img, max_width, max_height)
    width, height = img.size

    # Ensure dimensions are even
    if width % 2 != 0:
        width -= 1
    if height % 2 != 0:
        height -= 1

    img = img.crop((0, 0, width, height))
    pixels = img.load()

    # Process image in 2x2 blocks
    output = []
    for y in range(0, height, 2):
        row = ""
        for x in range(0, width, 2):
            # Get 2x2 pixel block colors
            colors = []
            for dy in range(2):
                for dx in range(2):
                    if y + dy < height and x + dx < width:
                        colors.append(pixels[x + dx, y + dy])
                    else:
                        colors.append((0, 0, 0))

            # Calculate average color
            avg_r = sum(c[0] for c in colors) // 4
            avg_g = sum(c[1] for c in colors) // 4
            avg_b = sum(c[2] for c in colors) // 4

            # Determine which pixels are "on" (brighter than average)
            threshold = (avg_r + avg_g + avg_b) // 3
            pattern = []
            for c in colors:
                brightness = sum(c) // 3
                pattern.append(1 if brightness > threshold else 0)

            # Get the appropriate block character
            block_char = BLOCKS.get(tuple(pattern), "█")

            # Apply average color
            row += rgb_to_ansi(avg_r, avg_g, avg_b, background=False)
            row += block_char

        row += "\033[0m"
        output.append(row)

    print("\n".join(output))


def main():
    image_path = "/Users/aaryanshsahay/Downloads/The_Strokes_-_Ist_Tis_It_US_cover.png"

    # Try different display modes
    print("Testing image display in terminal...")
    print("\n" + "=" * 60)
    print("Using half-blocks (best quality):")
    print("=" * 60 + "\n")

    try:
        display_image_unicode_blocks(image_path, max_width=60, max_height=30)
    except Exception as e:
        print(f"Error with half-blocks: {e}")
        # Try with a different image if the first one fails
        try:
            # Create a simple test image
            from PIL import Image

            # Create a gradient test image
            img = Image.new("RGB", (100, 100))
            pixels = img.load()
            for y in range(100):
                for x in range(100):
                    r = int(255 * x / 100)
                    g = int(255 * y / 100)
                    b = 128
                    pixels[x, y] = (r, g, b)

            # Save and display
            test_path = "/tmp/test_gradient.png"
            img.save(test_path)

            print("\nDisplaying test gradient image:")
            display_image_unicode_blocks(test_path, max_width=40, max_height=20)

        except Exception as e2:
            print(f"Error creating test image: {e2}", file=sys.stderr)


file_path = "/Users/aaryanshsahay/Downloads/WhatsApp Image 2025-08-24 at 14.56.36.jpeg"

display_image_unicode_blocks(file_path, max_width=40, max_height=40)
