import asyncio
import paraview.modules.vtkRemotingPythonAsyncCore as asyncCore


class ParaT(object):
    """PythonApplication is a wrapper around vtkPVApplication for python that
    takes care of initializing vtkPVApplication with the event loop of asyncio
    which is required in order to allow waiting on futures while processing
    other application events."""

    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super(ParaT, cls).__new__(cls)
        return cls.__instance

    async def initialize(self, applicationName="python"):
        """initialize PVApplication with the current event loop.
        applicationName is used to identify the application and the main thread in the logs
        """
        Loop = asyncCore.vtkPythonRunLoop.GetInstance()
        App = asyncCore.vtkPVPythonApplication.GetInstance()
        if Loop is None:
            Loop = asyncCore.vtkPythonRunLoop()

        Loop.AcquireRunningLoopFromPython()

        self.__Loop = Loop

        if App is None:
            App = asyncCore.vtkPVPythonApplication()
            App.InitializeUsingPython(applicationName)

        self.__Application = App

        sessionId = await asyncCore.vtkPythonObservableWrapperUtilities.GetFuture(
            App.CreateBuiltinSession()
        )
        return self.__Application.GetSession(sessionId)

    async def finalize(self):
        """Shutdown the services and the associated endpoints"""
        assert self.__Application is not None
        self.__Application.Finalize()
        self.__Application = None
        self.__Loop = None
