#!/usr/bin/env python3
"""
Demo script showing the new graph-based DSL for pipeline configuration.

This demonstrates how to define pipelines using the graph abstraction,
which is more intuitive than the verbose XYZStage naming convention.
"""

from engine.effects.plugins import discover_plugins
from engine.pipeline.graph import Graph, NodeType
from engine.pipeline.graph_adapter import graph_to_pipeline, dict_to_pipeline


def demo_imperative_api():
    """Demo: Imperative Python API for building graphs."""
    print("=== Imperative Python API ===")

    graph = Graph()
    graph.node("source", NodeType.SOURCE, source="headlines")
    graph.node("camera", NodeType.CAMERA, mode="scroll", speed=1.0)
    graph.node("noise", NodeType.EFFECT, effect="noise", intensity=0.3)
    graph.node("display", NodeType.DISPLAY, backend="null")

    # Connect nodes in a chain
    graph.chain("source", "camera", "noise", "display")

    # Validate the graph
    errors = graph.validate()
    if errors:
        print(f"Validation errors: {errors}")
        return

    # Convert to pipeline
    pipeline = graph_to_pipeline(graph, viewport_width=80, viewport_height=24)

    print(f"Pipeline created with {len(pipeline._stages)} stages:")
    for name, stage in pipeline._stages.items():
        print(f"  - {name}: {stage.__class__.__name__}")

    return pipeline


def demo_dict_api():
    """Demo: Dictionary-based API for building graphs."""
    print("\n=== Dictionary API ===")

    data = {
        "nodes": {
            "source": "headlines",
            "camera": {"type": "camera", "mode": "scroll", "speed": 1.0},
            "noise": {"type": "effect", "effect": "noise", "intensity": 0.5},
            "fade": {"type": "effect", "effect": "fade", "intensity": 0.8},
            "display": {"type": "display", "backend": "null"},
        },
        "connections": ["source -> camera -> noise -> fade -> display"],
    }

    pipeline = dict_to_pipeline(data, viewport_width=80, viewport_height=24)

    print(f"Pipeline created with {len(pipeline._stages)} stages:")
    for name, stage in pipeline._stages.items():
        print(f"  - {name}: {stage.__class__.__name__}")

    return pipeline


def demo_graph_validation():
    """Demo: Graph validation."""
    print("\n=== Graph Validation ===")

    # Create a graph with a cycle
    graph = Graph()
    graph.node("a", NodeType.SOURCE)
    graph.node("b", NodeType.CAMERA)
    graph.node("c", NodeType.DISPLAY)
    graph.connect("a", "b")
    graph.connect("b", "c")
    graph.connect("c", "a")  # Creates cycle

    errors = graph.validate()
    print(f"Cycle detection errors: {errors}")

    # Create a valid graph
    graph2 = Graph()
    graph2.node("source", NodeType.SOURCE, source="headlines")
    graph2.node("display", NodeType.DISPLAY, backend="null")
    graph2.connect("source", "display")

    errors2 = graph2.validate()
    print(f"Valid graph errors: {errors2}")


def demo_node_types():
    """Demo: Different node types."""
    print("\n=== Node Types ===")

    graph = Graph()

    # Source node
    graph.node("headlines", NodeType.SOURCE, source="headlines")
    print("✓ Source node created")

    # Camera node with different modes
    graph.node("camera_scroll", NodeType.CAMERA, mode="scroll", speed=1.0)
    graph.node("camera_feed", NodeType.CAMERA, mode="feed", speed=0.5)
    graph.node("camera_horizontal", NodeType.CAMERA, mode="horizontal", speed=1.0)
    print("✓ Camera nodes created (scroll, feed, horizontal)")

    # Effect nodes
    graph.node("noise", NodeType.EFFECT, effect="noise", intensity=0.3)
    graph.node("fade", NodeType.EFFECT, effect="fade", intensity=0.8)
    print("✓ Effect nodes created (noise, fade)")

    # Positioning node
    graph.node("position", NodeType.POSITION, mode="mixed")
    print("✓ Positioning node created")

    # Display nodes
    graph.node("terminal", NodeType.DISPLAY, backend="terminal")
    graph.node("null", NodeType.DISPLAY, backend="null")
    print("✓ Display nodes created")

    print(f"\nTotal nodes: {len(graph.nodes)}")


if __name__ == "__main__":
    # Discover effect plugins first
    discover_plugins()

    # Run demos
    demo_imperative_api()
    demo_dict_api()
    demo_graph_validation()
    demo_node_types()

    print("\n=== Demo Complete ===")
