#!/usr/bin/env python3
"""Generate screenshots for procgen cookbook recipes.

Uses Frame-based visualization since Grid cell colors use ColorLayer API.
"""
import mcrfpy
import os
import docs_output
from mcrfpy import automation
import sys

OUTPUT_DIR = docs_output.image_dir("cookbook")  # #372: was a hardcoded absolute path

# Simple PRNG
_seed = 42

def random():
    global _seed
    _seed = (_seed * 1103515245 + 12345) & 0x7fffffff
    return (_seed >> 16) / 32768.0

def seed(n):
    global _seed
    _seed = n

def choice(lst):
    return lst[int(random() * len(lst))]


def screenshot_cellular_caves():
    """Generate cellular automata caves visualization."""
    print("Generating cellular automata caves...")

    scene = mcrfpy.Scene("caves")
    scene.activate()
    mcrfpy.step(0.1)

    # Background
    bg = mcrfpy.Frame(pos=(0, 0), size=(640, 500))
    bg.fill_color = mcrfpy.Color(15, 15, 25)
    scene.children.append(bg)

    width, height = 50, 35
    cell_size = 12
    seed(42)

    # Store cell data
    cells = [[False for _ in range(width)] for _ in range(height)]

    # Step 1: Random noise (45% walls)
    for y in range(height):
        for x in range(width):
            if x == 0 or x == width-1 or y == 0 or y == height-1:
                cells[y][x] = True  # Border walls
            else:
                cells[y][x] = random() < 0.45

    # Step 2: Smooth with cellular automata (5 iterations)
    for _ in range(5):
        new_cells = [[cells[y][x] for x in range(width)] for y in range(height)]
        for y in range(1, height - 1):
            for x in range(1, width - 1):
                wall_count = sum(
                    1 for dy in [-1, 0, 1] for dx in [-1, 0, 1]
                    if not (dx == 0 and dy == 0) and cells[y + dy][x + dx]
                )
                if wall_count >= 5:
                    new_cells[y][x] = True
                elif wall_count <= 3:
                    new_cells[y][x] = False
        cells = new_cells

    # Find largest connected region
    visited = set()
    regions = []

    def flood_fill(start_x, start_y):
        result = []
        stack = [(start_x, start_y)]
        while stack:
            x, y = stack.pop()
            if (x, y) in visited or x < 0 or x >= width or y < 0 or y >= height:
                continue
            if cells[y][x]:  # Wall
                continue
            visited.add((x, y))
            result.append((x, y))
            stack.extend([(x+1, y), (x-1, y), (x, y+1), (x, y-1)])
        return result

    for y in range(height):
        for x in range(width):
            if (x, y) not in visited and not cells[y][x]:
                region = flood_fill(x, y)
                if region:
                    regions.append(region)

    largest = max(regions, key=len) if regions else []
    largest_set = set(largest)

    # Draw cells as colored frames
    for y in range(height):
        for x in range(width):
            px = 20 + x * cell_size
            py = 20 + y * cell_size
            cell = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))

            if cells[y][x]:
                cell.fill_color = mcrfpy.Color(60, 40, 30)  # Wall
            elif (x, y) in largest_set:
                cell.fill_color = mcrfpy.Color(50, 90, 100)  # Main cave
            else:
                cell.fill_color = mcrfpy.Color(45, 35, 30)  # Filled region

            scene.children.append(cell)

    # Title
    title = mcrfpy.Caption(text="Cellular Automata Caves", pos=(20, 445))
    title.fill_color = mcrfpy.Color(200, 200, 200)
    title.font_size = 18
    scene.children.append(title)

    subtitle = mcrfpy.Caption(text="45% fill, 5 iterations, largest region preserved", pos=(20, 468))
    subtitle.fill_color = mcrfpy.Color(130, 130, 140)
    subtitle.font_size = 12
    scene.children.append(subtitle)

    mcrfpy.step(0.1)
    automation.screenshot(OUTPUT_DIR + "/procgen_cellular_caves.png")
    print("Saved: procgen_cellular_caves.png")


def screenshot_wfc():
    """Generate WFC pattern visualization."""
    print("Generating WFC patterns...")

    scene = mcrfpy.Scene("wfc")
    scene.activate()
    mcrfpy.step(0.1)

    # Background
    bg = mcrfpy.Frame(pos=(0, 0), size=(640, 500))
    bg.fill_color = mcrfpy.Color(15, 20, 15)
    scene.children.append(bg)

    width, height = 40, 28
    cell_size = 15
    seed(123)

    GRASS, DIRT, WATER, SAND = 0, 1, 2, 3
    colors = {
        GRASS: mcrfpy.Color(60, 120, 50),
        DIRT: mcrfpy.Color(100, 70, 40),
        WATER: mcrfpy.Color(40, 80, 140),
        SAND: mcrfpy.Color(180, 160, 90)
    }

    rules = {
        GRASS: {'N': [GRASS, DIRT, SAND], 'S': [GRASS, DIRT, SAND],
                'E': [GRASS, DIRT, SAND], 'W': [GRASS, DIRT, SAND]},
        DIRT:  {'N': [GRASS, DIRT], 'S': [GRASS, DIRT],
                'E': [GRASS, DIRT], 'W': [GRASS, DIRT]},
        WATER: {'N': [WATER, SAND], 'S': [WATER, SAND],
                'E': [WATER, SAND], 'W': [WATER, SAND]},
        SAND:  {'N': [GRASS, WATER, SAND], 'S': [GRASS, WATER, SAND],
                'E': [GRASS, WATER, SAND], 'W': [GRASS, WATER, SAND]}
    }

    tiles = set(rules.keys())
    possibilities = {(x, y): set(tiles) for y in range(height) for x in range(width)}
    result = {}

    # Seed water lake
    for x in range(22, 32):
        for y in range(8, 18):
            possibilities[(x, y)] = {WATER}
            result[(x, y)] = WATER

    # Seed dirt path
    for y in range(10, 18):
        possibilities[(3, y)] = {DIRT}
        result[(3, y)] = DIRT

    directions = {'N': (0, -1), 'S': (0, 1), 'E': (1, 0), 'W': (-1, 0)}

    def propagate(sx, sy):
        stack = [(sx, sy)]
        while stack:
            x, y = stack.pop()
            current = possibilities[(x, y)]
            for dir_name, (dx, dy) in directions.items():
                nx, ny = x + dx, y + dy
                if not (0 <= nx < width and 0 <= ny < height):
                    continue
                neighbor = possibilities[(nx, ny)]
                if len(neighbor) == 1:
                    continue
                allowed = set()
                for tile in current:
                    if dir_name in rules[tile]:
                        allowed.update(rules[tile][dir_name])
                new_opts = neighbor & allowed
                if new_opts and new_opts != neighbor:
                    possibilities[(nx, ny)] = new_opts
                    stack.append((nx, ny))

    # Propagate from seeds
    for x in range(22, 32):
        for y in range(8, 18):
            propagate(x, y)
    for y in range(10, 18):
        propagate(3, y)

    # Collapse
    for _ in range(width * height):
        best, best_e = None, 1000.0
        for pos, opts in possibilities.items():
            if len(opts) > 1:
                e = len(opts) + random() * 0.1
                if e < best_e:
                    best_e, best = e, pos

        if best is None:
            break

        x, y = best
        opts = list(possibilities[(x, y)])
        if not opts:
            break

        weights = {GRASS: 5, DIRT: 2, WATER: 1, SAND: 2}
        weighted = []
        for t in opts:
            weighted.extend([t] * weights.get(t, 1))
        chosen = choice(weighted) if weighted else GRASS

        possibilities[(x, y)] = {chosen}
        result[(x, y)] = chosen
        propagate(x, y)

    # Fill remaining
    for y in range(height):
        for x in range(width):
            if (x, y) not in result:
                opts = list(possibilities[(x, y)])
                result[(x, y)] = choice(opts) if opts else GRASS

    # Draw
    for y in range(height):
        for x in range(width):
            px = 20 + x * cell_size
            py = 20 + y * cell_size
            cell = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
            cell.fill_color = colors[result[(x, y)]]
            scene.children.append(cell)

    # Title
    title = mcrfpy.Caption(text="Wave Function Collapse", pos=(20, 445))
    title.fill_color = mcrfpy.Color(200, 200, 200)
    title.font_size = 18
    scene.children.append(title)

    subtitle = mcrfpy.Caption(text="Constraint-based terrain (seeded lake + path)", pos=(20, 468))
    subtitle.fill_color = mcrfpy.Color(130, 140, 130)
    subtitle.font_size = 12
    scene.children.append(subtitle)

    # Legend
    for i, (name, tid) in enumerate([("Grass", GRASS), ("Dirt", DIRT), ("Sand", SAND), ("Water", WATER)]):
        lx, ly = 480, 445 + i * 14
        swatch = mcrfpy.Frame(pos=(lx, ly), size=(12, 12))
        swatch.fill_color = colors[tid]
        scene.children.append(swatch)
        label = mcrfpy.Caption(text=name, pos=(lx + 16, ly))
        label.fill_color = mcrfpy.Color(150, 150, 150)
        label.font_size = 11
        scene.children.append(label)

    mcrfpy.step(0.1)
    automation.screenshot(OUTPUT_DIR + "/procgen_wfc.png")
    print("Saved: procgen_wfc.png")


if __name__ == "__main__":
    screenshot_cellular_caves()
    screenshot_wfc()
    print("\nDone!")
    sys.exit(0)
