
import time

import numpy as np

import viser


server = viser.ViserServer()

# Add some common GUI elements: number inputs, sliders, vectors, checkboxes.
with server.gui.add_folder("Read-only"):
    gui_counter = server.gui.add_number(
        "Counter",
        initial_value=0,
        disabled=True,
    )
    gui_slider = server.gui.add_slider(
        "Slider",
        min=0,
        max=100,
        step=1,
        initial_value=0,
        disabled=True,
    )
    #gui_progress = server.gui.add_progress_bar(25, animated=True)

with server.gui.add_folder("Editable"):
    gui_vector2 = server.gui.add_vector2(
        "Position",
        initial_value=(0.0, 0.0),
        step=0.1,
    )
    gui_vector3 = server.gui.add_vector3(
        "Size",
        initial_value=(1.0, 1.0, 1.0),
        step=0.25,
    )
    with server.gui.add_folder("Text toggle"):
        gui_checkbox_hide = server.gui.add_checkbox(
            "Hide",
            initial_value=False,
        )
        gui_text = server.gui.add_text(
            "Text",
            initial_value="Hello world",
        )
        gui_button = server.gui.add_button("Button")
        gui_checkbox_disable = server.gui.add_checkbox(
            "Disable",
            initial_value=False,
        )
        gui_rgb = server.gui.add_rgb(
            "Color",
            initial_value=(255, 255, 0),
        )
        gui_multi_slider = server.gui.add_multi_slider(
            "Multi slider",
            min=0,
            max=100,
            step=1,
            initial_value=(0, 30, 100),
            marks=((0, "0"), (50, "5"), (70, "7"), 99),
        )
        gui_slider_positions = server.gui.add_slider(
            "# sliders",
            min=0,
            max=10,
            step=1,
            initial_value=3,
            marks=((0, "0"), (5, "5"), (7, "7"), 10),
        )
        gui_upload_button = server.gui.add_upload_button(
            "Upload", icon=viser.Icon.UPLOAD
        )

@gui_upload_button.on_upload
def _(_) -> None:
    """Callback for when a file is uploaded."""
    file = gui_upload_button.value
    print(file.name, len(file.content), "bytes")

# Pre-generate a point cloud to send.
point_positions = np.random.uniform(low=-1.0, high=1.0, size=(5000, 3))
color_coeffs = np.random.uniform(0.4, 1.0, size=(point_positions.shape[0]))

counter = 0
while True:
    # We can set the value of an input to a particular value. Changes are
    # automatically reflected in connected clients.
    gui_counter.value = counter
    gui_slider.value = counter % 100

    # We can set the position of a scene node with `.position`, and read the value
    # of a gui element with `.value`. Changes are automatically reflected in
    # connected clients.
    server.scene.add_point_cloud(
        "/point_cloud",
        points=point_positions * np.array(gui_vector3.value, dtype=np.float32),
        colors=(
            np.tile(gui_rgb.value, point_positions.shape[0]).reshape((-1, 3))
            * color_coeffs[:, None]
        ).astype(np.uint8),
        position=gui_vector2.value + (0,),
        point_shape="circle",
    )


    # We can use `.visible` and `.disabled` to toggle GUI elements.
    gui_text.visible = not gui_checkbox_hide.value
    gui_button.visible = not gui_checkbox_hide.value
    gui_rgb.disabled = gui_checkbox_disable.value
    gui_button.disabled = gui_checkbox_disable.value
    gui_upload_button.disabled = gui_checkbox_disable.value

    # Update the number of handles in the multi-slider.
    if gui_slider_positions.value != len(gui_multi_slider.value):
        gui_multi_slider.value = np.linspace(
            0, 100, gui_slider_positions.value, dtype=np.int64
        )

    counter += 1
    time.sleep(0.01)

