import asyncio

from parat.services import ApplyController, ParaT, PipelineBuilder, PropertyManager
from paraview.modules.vtkRemotingPythonAsyncCore import vtkPythonObservableWrapperUtilities
import vtk
import sys

EventCount = 0
cond = asyncio.Condition()

async def monitorViewOutput(view):

    global cond
    async for _ in vtkPythonObservableWrapperUtilities.GetIterator(
        view.GetViewOutputObservable()
    ):
        async with cond:
            cond.notify_all()

async def ObserveApply(acontroller):
    global EventCount
    async for event in acontroller.GetObservable():
        print(event)
        EventCount += 1


async def main():
    App = ParaT()
    session = await App.initialize()

    builder = PipelineBuilder(session)
    acontroller = ApplyController(session)
    task = asyncio.create_task(ObserveApply(acontroller))

    wavelet = await builder.CreateProxy("sources", "RTAnalyticSource")

    contour = await builder.CreateProxy("filters", "Contour", Input=wavelet)

    pmanager = PropertyManager()
    # See all the available properties
    print(pmanager.GetValues(contour))

    pmanager.SetValues(
        contour,
        ContourValues=[
            37.35310363769531,
            63.961517333984375,
            90.56993103027344,
            117.1783447265625,
            143.78675842285156,
            170.39517211914062,
            197.0035858154297,
            223.61199951171875,
            250.2204132080078,
            276.8288269042969,
        ],
        SelectInputScalars=["", "", "", "", "RTData"],
        force_push=True,
    )

    view = await builder.CreateProxy("views", "RenderView")
    pmanager.SetValues(view, StreamOutput=True, force_push=True)
    viewResultTask = asyncio.create_task(monitorViewOutput(view))

    # before we 'update' the view, let's install an interactor on the view
    # so that the viewport dimensions, cameras of the client and server's render windows sync up.
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(view.GetRenderWindow())
    # Apply will call UpdatePipeline() for proxies created since last time.
    # Create representations for them and apply any scalar coloring if available and update the view
    acontroller.Apply()
    await asyncio.sleep(0.01)

    if "-I" in sys.argv:
        while not iren.GetDone():
            iren.ProcessEvents()
            await asyncio.sleep(0.01)
    else:
        for i in range(5):
            view.GetCamera().Azimuth(10)
            view.StillRender()
            async with cond:
                await cond.wait()

    view.UnsubscribeOutputStreams()
    await viewResultTask

    acontroller.Unsubscribe()
    await task
    assert EventCount == 1
    print("Done")
    await App.finalize()


asyncio.run(main())
