# Hybrid Preset-Graph Configuration

The hybrid configuration format combines the simplicity of presets with the flexibility of graphs, providing a concise way to define pipelines.

## Overview

The hybrid format uses **70% less space** than the verbose node-based DSL while providing the same functionality.

### Comparison

**Verbose Node DSL (39 lines):**
```toml
[nodes.source]
type = "source"
source = "headlines"

[nodes.camera]
type = "camera"
mode = "scroll"
speed = 1.0

[nodes.noise]
type = "effect"
effect = "noise"
intensity = 0.3

[nodes.display]
type = "display"
backend = "terminal"

[connections]
list = ["source -> camera -> noise -> display"]
```

**Hybrid Config (20 lines):**
```toml
[pipeline]
source = "headlines"

camera = { mode = "scroll", speed = 1.0 }

effects = [
    { name = "noise", intensity = 0.3 }
]

display = { backend = "terminal" }
```

## Syntax

### Basic Structure

```toml
[pipeline]
source = "headlines"
camera = { mode = "scroll", speed = 1.0 }
effects = [
    { name = "noise", intensity = 0.3 },
    { name = "fade", intensity = 0.5 }
]
display = { backend = "terminal", positioning = "mixed" }
```

### Configuration Options

#### Source
```toml
source = "headlines"  # Built-in source: headlines, poetry, empty, etc.
```

#### Camera
```toml
# Inline object notation
camera = { mode = "scroll", speed = 1.0 }

# Or shorthand (uses defaults)
camera = "scroll"
```

Available modes: `scroll`, `feed`, `horizontal`, `omni`, `floating`, `bounce`, `radial`

#### Effects
```toml
# Array of effect configurations
effects = [
    { name = "noise", intensity = 0.3 },
    { name = "fade", intensity = 0.5, enabled = true }
]

# Or shorthand (uses defaults)
effects = ["noise", "fade"]
```

Available effects: `noise`, `fade`, `glitch`, `firehose`, `tint`, `hud`, etc.

#### Display
```toml
# Inline object notation
display = { backend = "terminal", positioning = "mixed" }

# Or shorthand
display = "terminal"
```

Available backends: `terminal`, `null`, `websocket`, `pygame`

### Viewport Settings
```toml
[pipeline]
viewport_width = 80
viewport_height = 24
```

## Usage Examples

### Minimal Configuration
```toml
[pipeline]
source = "headlines"
display = "terminal"
```

### With Camera and Effects
```toml
[pipeline]
source = "headlines"
camera = { mode = "scroll", speed = 1.0 }
effects = [
    { name = "noise", intensity = 0.3 },
    { name = "fade", intensity = 0.5 }
]
display = { backend = "terminal", positioning = "mixed" }
```

### Full Configuration
```toml
[pipeline]
source = "poetry"
camera = { mode = "scroll", speed = 1.5 }
effects = [
    { name = "noise", intensity = 0.2 },
    { name = "fade", intensity = 0.4 },
    { name = "glitch", intensity = 0.3 },
    { name = "firehose", intensity = 0.5 }
]
display = { backend = "terminal", positioning = "mixed" }
viewport_width = 100
viewport_height = 30
```

## Python API

### Loading from TOML File
```python
from engine.pipeline.hybrid_config import load_hybrid_config

config = load_hybrid_config("examples/hybrid_config.toml")
pipeline = config.to_pipeline()
```

### Creating Config Programmatically
```python
from engine.pipeline.hybrid_config import (
    PipelineConfig,
    CameraConfig,
    EffectConfig,
    DisplayConfig,
)

config = PipelineConfig(
    source="headlines",
    camera=CameraConfig(mode="scroll", speed=1.0),
    effects=[
        EffectConfig(name="noise", intensity=0.3),
        EffectConfig(name="fade", intensity=0.5),
    ],
    display=DisplayConfig(backend="terminal", positioning="mixed"),
)

pipeline = config.to_pipeline(viewport_width=80, viewport_height=24)
```

### Converting to Graph
```python
from engine.pipeline.hybrid_config import PipelineConfig

config = PipelineConfig(source="headlines", display={"backend": "terminal"})
graph = config.to_graph()  # Returns Graph object for further manipulation
```

## How It Works

The hybrid config system:

1. **Parses TOML** into a `PipelineConfig` dataclass
2. **Converts to Graph** internally using automatic linear connections
3. **Reuses existing adapter** to convert graph to pipeline stages
4. **Maintains backward compatibility** with verbose node DSL

### Automatic Connection Logic

The system automatically creates linear connections:
```
source -> camera -> effects[0] -> effects[1] -> ... -> display
```

This covers 90% of use cases. For complex DAGs, use the verbose node DSL.

## Migration Guide

### From Presets
The hybrid format is very similar to presets:

**Preset:**
```toml
[presets.custom]
source = "headlines"
effects = ["noise", "fade"]
display = "terminal"
```

**Hybrid:**
```toml
[pipeline]
source = "headlines"
effects = ["noise", "fade"]
display = "terminal"
```

The main difference is using `[pipeline]` instead of `[presets.custom]`.

### From Verbose Node DSL
**Old (39 lines):**
```toml
[nodes.source] type = "source" source = "headlines"
[nodes.camera] type = "camera" mode = "scroll"
[nodes.noise] type = "effect" effect = "noise" intensity = 0.3
[nodes.display] type = "display" backend = "terminal"
[connections] list = ["source -> camera -> noise -> display"]
```

**New (14 lines):**
```toml
[pipeline]
source = "headlines"
camera = { mode = "scroll" }
effects = [{ name = "noise", intensity = 0.3 }]
display = { backend = "terminal" }
```

## When to Use Each Format

| Format | Use When | Lines (example) |
|--------|----------|-----------------|
| **Preset** | Simple configurations, no effect intensity tuning | 10 |
| **Hybrid** | Most common use cases, need intensity tuning | 20 |
| **Verbose Node DSL** | Complex DAGs, branching, custom connections | 39 |
| **Python API** | Dynamic configuration, programmatic generation | N/A |

## Examples

See `examples/hybrid_config.toml` for a complete working example.

Run the demo:
```bash
python examples/hybrid_visualization.py
```
