import gradio as gr

def increment_counter(current_count):
    """Function that increments the counter and returns updated state and display."""
    new_count = current_count + 1
    return new_count, f"Count: {new_count}"

def decrement_counter(current_count):
    """Function that decrements the counter and returns updated state and display."""
    new_count = current_count - 1
    return new_count, f"Count: {new_count}"

def reset_counter():
    """Function that resets the counter to zero."""
    return 0, "Count: 0"

def multiply_counter(current_count, multiplier):
    """Function that multiplies the counter by a given value."""
    new_count = current_count * multiplier
    return new_count, f"Count: {new_count}"

def get_interface(container):
    """
    Demo interface showing how to use gr.State for maintaining state across interactions.

    This example shows:
    1. How to create a gr.State object
    2. How to pass state between function calls
    3. How to update state and UI components together
    4. How to use state with multiple inputs
    """
    with container:
        gr.Markdown("# Gradio State Demo")
        gr.Markdown("This demo shows how to use `gr.State` to maintain data across button clicks.")

        # Create a state object to hold the counter value
        counter_state = gr.State(value=0)

        # Display components
        with gr.Row():
            counter_display = gr.Textbox(
                value="Count: 0",
                label="Current Counter",
                interactive=False
            )

        # Control buttons
        with gr.Row():
            increment_btn = gr.Button("➕ Increment", variant="primary")
            decrement_btn = gr.Button("➖ Decrement", variant="secondary")
            reset_btn = gr.Button("🔄 Reset", variant="stop")

        # Advanced controls
        with gr.Row():
            multiplier_input = gr.Number(value=2, label="Multiplier")
            multiply_btn = gr.Button("✖️ Multiply", variant="secondary")

        # Wire up the button click handlers
        increment_btn.click(
            fn=increment_counter,
            inputs=[counter_state],  # Pass the current state
            outputs=[counter_state, counter_display]  # Update both state and display
        )

        decrement_btn.click(
            fn=decrement_counter,
            inputs=[counter_state],
            outputs=[counter_state, counter_display]
        )

        reset_btn.click(
            fn=reset_counter,
            inputs=[],  # No inputs needed for reset
            outputs=[counter_state, counter_display]
        )

        multiply_btn.click(
            fn=multiply_counter,
            inputs=[counter_state, multiplier_input],  # Multiple inputs including state
            outputs=[counter_state, counter_display]
        )

        # Information section
        gr.Markdown("""
        ## How gr.State Works:

        1. **Create State**: `counter_state = gr.State(value=0)` creates a state object with initial value
        2. **Pass as Input**: Include state in the `inputs=[]` list of your click handler
        3. **Return Updated State**: Your function should return the new state value
        4. **Update Multiple Outputs**: Return tuple with `(new_state, updated_ui_components)`

        ## Key Benefits:
        - ✅ Maintains data between user interactions
        - ✅ Allows complex state management
        - ✅ Works with multiple inputs and outputs
        - ✅ State is preserved across UI updates

        ## Example from winget.py:
        ```python
        # Create state to track category info
        category_state = gr.State(value=(category_name, installed_count, total_count))

        # Use in click handler
        toggle_btn.click(
            fn=toggle_package,
            inputs=[category_state],  # Pass current state
            outputs=[toggle_btn, category_state, accordion]  # Update button, state, and accordion
        )
        ```
        """)

if __name__ == "__main__":
    # Run the demo standalone
    with gr.Blocks(title="Gradio State Demo") as demo:
        get_interface(demo)

    demo.launch()