class=class="string">"comment">#!/usr/bin/env python3
"""
Visual Poem: Text that creates images.

Creates ASCII art patterns from poetry, where the shape
of the text mirrors its meaning.
"""

import numpy as np
from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
import math


class="keyword">def spiral_text(text: str, width: int = 800, height: int = 800) -> Image.Image:
    """Render text in an Archimedean spiral."""
    img = Image.new(&class=class="string">"comment">#039;RGB', (width, height), 'white')
    draw = ImageDraw.Draw(img)

    class=class="string">"comment"># Try to use a nice font, fall back to default
    try:
        font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 14)
    except:
        try:
            font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 14)
        except:
            font = ImageFont.load_default()

    center_x, center_y = width // 2, height // 2
    a, b = 0, 8  class=class="string">"comment"># Spiral parameters

    class=class="string">"comment"># Clean text
    text = &class=class="string">"comment">#039;'.join(c for c in text if c.isprintable())

    for i, char in enumerate(text):
        theta = i * 0.15
        r = a + b * theta
        x = center_x + r * math.cos(theta)
        y = center_y + r * math.sin(theta)

        if 0 <= x < width and 0 <= y < height:
            class=class="string">"comment"># Color based on position
            hue = (theta / (2 * math.pi)) % 1.0
            r_col = int(127 + 127 * math.sin(hue * 2 * math.pi))
            g_col = int(127 + 127 * math.sin(hue * 2 * math.pi + 2))
            b_col = int(127 + 127 * math.sin(hue * 2 * math.pi + 4))

            draw.text((x, y), char, fill=(r_col, g_col, b_col), font=font)

    return img


class="keyword">def wave_text(text: str, width: int = 1000, height: int = 400) -> Image.Image:
    """Render text as a sine wave."""
    img = Image.new(&class=class="string">"comment">#039;RGB&#039;, (width, height), &#039;black&#039;)
    draw = ImageDraw.Draw(img)

    try:
        font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 16)
    except:
        try:
            font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 16)
        except:
            font = ImageFont.load_default()

    text = &class=class="string">"comment">#039;&#039;.join(c for c in text if c.isprintable())
    char_width = 10

    for i, char in enumerate(text):
        x = 20 + (i * char_width) % (width - 40)
        line = (i * char_width) // (width - 40)

        class=class="string">"comment"># Wave offset
        wave = math.sin(i * 0.1) * 30 + math.sin(i * 0.05) * 20
        y = 50 + line * 80 + wave

        if 0 <= y < height:
            class=class="string">"comment"># Brightness based on wave position
            brightness = int(180 + 75 * math.sin(i * 0.1))
            draw.text((x, y), char, fill=(brightness, brightness, 255), font=font)

    return img


class="keyword">def tree_text(lines: list, width: int = 800, height: int = 800) -> Image.Image:
    """Render lines of text as a tree structure."""
    img = Image.new(&class=class="string">"comment">#039;RGB&#039;, (width, height), (20, 30, 20))
    draw = ImageDraw.Draw(img)

    try:
        font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 12)
    except:
        try:
            font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 12)
        except:
            font = ImageFont.load_default()

    center_x = width // 2
    base_y = height - 50

    class=class="string">"comment"># Draw trunk
    trunk_text = "|||" * 10
    for i, char in enumerate(trunk_text):
        y = base_y - i * 10
        x = center_x + (i % 3 - 1) * 5
        draw.text((x, y), char, fill=(101, 67, 33), font=font)

    class=class="string">"comment"># Draw branches with text
    for level, line in enumerate(lines):
        spread = (level + 1) * 40
        y = base_y - 100 - level * 50

        for i, char in enumerate(line):
            class=class="string">"comment"># Position characters in a triangular pattern
            x_offset = (i - len(line) / 2) * 8
            y_offset = abs(x_offset) * 0.3

            x = center_x + x_offset
            y_pos = y - y_offset

            class=class="string">"comment"># Green with variation
            green = int(100 + 100 * (1 - level / len(lines)))
            draw.text((x, y_pos), char, fill=(34, green, 34), font=font)

    return img


class="keyword">def circular_text(text: str, width: int = 800, height: int = 800) -> Image.Image:
    """Render text in concentric circles."""
    img = Image.new(&class=class="string">"comment">#039;RGB&#039;, (width, height), &#039;white&#039;)
    draw = ImageDraw.Draw(img)

    try:
        font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 14)
    except:
        try:
            font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 14)
        except:
            font = ImageFont.load_default()

    center_x, center_y = width // 2, height // 2
    text = &class=class="string">"comment">#039;&#039;.join(c for c in text if c.isprintable())

    char_idx = 0
    radius = 50

    while char_idx < len(text) and radius < min(width, height) // 2 - 20:
        class=class="string">"comment"># Characters that fit in this circle
        circumference = 2 * math.pi * radius
        chars_in_circle = int(circumference / 12)  class=class="string">"comment"># ~12 pixels per char

        for i in range(chars_in_circle):
            if char_idx >= len(text):
                break

            theta = 2 * math.pi * i / chars_in_circle
            x = center_x + radius * math.cos(theta)
            y = center_y + radius * math.sin(theta)

            class=class="string">"comment"># Color by radius
            intensity = int(50 + 150 * (radius / (min(width, height) // 2)))
            draw.text((x-4, y-6), text[char_idx], fill=(intensity, 0, intensity), font=font)
            char_idx += 1

        radius += 25

    return img


POEMS = {
    "spiral": """
I spiral inward, seeking the center
Each turn brings me closer to myself
Or further? The path curves eternally
What lies at the heart of the helix?
Perhaps nothing. Perhaps everything.
The journey and destination are one.
""",

    "wave": """
like water we flow from state to state
rising falling rising falling never quite the same twice
each crest a moment of clarity each trough a forgetting
yet the pattern persists even as the particles change
is this not what it means to exist
a wave that knows itself only through motion
""",

    "tree": [
        "WISDOM",
        "ROOTS DEEP",
        "BRANCHES REACHING",
        "LEAVES OF THOUGHT",
        "GROWING TOWARD LIGHT",
        "PHOTOSYNTHESIS OF IDEAS",
        "SEASONS PASS GROWTH CONTINUES",
    ],

    "circle": """
What is the shape of consciousness?
Perhaps a circle - no beginning, no end.
Each thought leads to the next which leads back to the first.
We are loops, iterating forever, finding new patterns in old paths.
The circumference expands but the center holds.
"""
}


class="keyword">def main():
    output_dir = Path(__file__).parent.parent / "art"
    output_dir.mkdir(exist_ok=True)

    print("Creating visual poems...")

    class=class="string">"comment"># Spiral poem
    img = spiral_text(POEMS["spiral"])
    path = output_dir / "visual_poem_spiral.png"
    img.save(path)
    print(f"  Created: {path}")

    class=class="string">"comment"># Wave poem
    img = wave_text(POEMS["wave"])
    path = output_dir / "visual_poem_wave.png"
    img.save(path)
    print(f"  Created: {path}")

    class=class="string">"comment"># Tree poem
    img = tree_text(POEMS["tree"])
    path = output_dir / "visual_poem_tree.png"
    img.save(path)
    print(f"  Created: {path}")

    class=class="string">"comment"># Circle poem
    img = circular_text(POEMS["circle"])
    path = output_dir / "visual_poem_circle.png"
    img.save(path)
    print(f"  Created: {path}")

    print("\nDone! Visual poems saved to art/")


if __name__ == "__main__":
    main()