"""
Example usage of the nono Python SDK.

This demonstrates how to use the SDK to interact with the nono server.
"""

import asyncio
from nono import (
    NonoClient,
    CallingFrame,
    OperationPushValue,
    OperationPopValue,
    OperationCall,
    ScriptFunc,
    Operation,
)


async def example_config():
    """Example: Read server configuration."""
    print("\n=== Config Example ===")
    async with NonoClient() as client:
        config = await client.config_read()
        print(f"Server config: {config.config}")


async def example_entities():
    """Example: Working with entities."""
    print("\n=== Entity Example ===")
    async with NonoClient() as client:
        # Write an entity
        entity_data = {"name": "Alice", "age": 30, "tags": ["developer", "python"]}
        await client.entity_write("user-1", entity_data)
        print(f"Wrote entity: user-1")

        # Read it back
        entity = await client.entity_read("user-1")
        print(f"Read entity: {entity}")

        # Try reading non-existent entity
        missing = await client.entity_read("non-existent")
        print(f"Missing entity: {missing}")  # Should be None


async def example_session_basic():
    """Example: Basic session operations."""
    print("\n=== Basic Session Example ===")
    async with NonoClient() as client:
        # Create a frame with some initial values
        frame = CallingFrame(
            calling_entity_id="example-entity",
            data={"step": 0},
            value_stack=[1, 2, 3],
            op_stack=[],
            handler_stack=[],
        )

        # Create session
        session_id = await client.session_create(
            name="example-session",
            data={"counter": 0, "status": "running"},
            frame=frame,
        )
        print(f"Created session: {session_id}")

        # Get session data
        data = await client.session_get_data(session_id)
        print(f"Session data: {data}")

        # Push a value to the frame
        await client.frame_push_value(session_id, {"new": "value"})
        print("Pushed value to frame")

        # Read frame data
        frame_data = await client.frame_read_data(session_id)
        print(f"Frame data: {frame_data}")

        # Update frame data
        await client.frame_write_data(session_id, {"step": 1, "updated": True})
        frame_data = await client.frame_read_data(session_id)
        print(f"Updated frame data: {frame_data}")

        # Delete session
        success = await client.session_delete(session_id)
        print(f"Deleted session: {success}")


async def example_session_with_operations():
    """Example: Session with VM operations."""
    print("\n=== Session with Operations Example ===")
    async with NonoClient() as client:
        # Create operations
        ops: list[Operation] = [
            OperationPopValue(),
            OperationPushValue(value=100),
            OperationPushValue(value=200),
        ]

        frame = CallingFrame(
            calling_entity_id="vm-test",
            data={},
            value_stack=[],
            op_stack=ops,
            handler_stack=[],
        )

        session_id = await client.session_create(
            name="vm-session",
            data={},
            frame=frame,
        )
        print(f"Created session: {session_id}")

        # Execute operations step by step
        step = 1
        while True:
            success = await client.session_next(session_id)
            if success:
                print(f"Step {step} executed successfully")
                step += 1
            else:
                print(f"Step {step} failed or no more operations")
                break

        # Clean up
        await client.session_delete(session_id)


async def example_script_execution():
    """Example: Executing a script via the VM."""
    print("\n=== Script Execution Example ===")
    async with NonoClient() as client:
        # Create an operation that calls echo
        call_op = OperationCall(
            func=ScriptFunc(exe="echo", args=["Hello from nono SDK!"])
        )

        frame = CallingFrame(
            calling_entity_id="script-test",
            data={},
            value_stack=[],
            op_stack=[call_op],
            handler_stack=[],
        )

        session_id = await client.session_create(
            name="script-session",
            data={},
            frame=frame,
        )
        print(f"Created session: {session_id}")

        # Execute the script
        success = await client.session_next(session_id)
        print(f"Script execution: {success}")

        # Clean up
        await client.session_delete(session_id)


async def example_dynamic_operations():
    """Example: Dynamically pushing operations."""
    print("\n=== Dynamic Operations Example ===")
    async with NonoClient() as client:
        # Create empty session
        frame = CallingFrame(
            calling_entity_id="dynamic-test",
            data={},
            value_stack=[],
            op_stack=[],
            handler_stack=[],
        )

        session_id = await client.session_create(
            name="dynamic-session",
            data={},
            frame=frame,
        )
        print(f"Created session: {session_id}")

        # Dynamically push operations
        await client.frame_push_op(
            session_id, value="first-value", op=OperationPopValue()
        )
        print("Pushed first operation")

        await client.frame_push_op(session_id, value=42, op=OperationPopValue())
        print("Pushed second operation")

        # Execute them
        await client.session_next(session_id)
        print("Executed first operation")

        await client.session_next(session_id)
        print("Executed second operation")

        # Clean up
        await client.session_delete(session_id)


async def main():
    """Run all examples."""
    print("=" * 60)
    print("nono Python SDK Examples")
    print("=" * 60)

    await example_config()
    await example_entities()
    await example_session_basic()
    await example_session_with_operations()
    await example_script_execution()
    await example_dynamic_operations()

    print("\n" + "=" * 60)
    print("All examples completed!")
    print("=" * 60)


if __name__ == "__main__":
    asyncio.run(main())
