import asyncio
from trame.app import get_server, asynchronous
from trame.ui.vuetify import SinglePageLayout
from trame.widgets import trame, vuetify, html


from parat.services import (
    ParaT,
    PipelineBuilder,
    DefinitionManager,
    ActiveObjects,
    PipelineViewer,
    PropertyManager,
)
from paraview.modules.vtkRemotingServerManagerCore import vtkPVDataInformation

from paraview.modules.vtkRemotingServerManager import vtkSMProxySelectionModel


# -----------------------------------------------------------------------------
# Trame app
# -----------------------------------------------------------------------------

server = get_server()
state, ctrl = server.state, server.controller

# -----------------------------------------------------------------------------
# State Setup
# -----------------------------------------------------------------------------
state.active_source = []
state.active_source_label = "None"
state.active_data_information = ""
state.git_tree = []


@state.change("active_source_label")
def print_active(active_source_label, **kwargs):
    print(f"Active is {active_source_label}")


@ctrl.add("on_server_ready")
def on_server_ready(**kwargs):
    print("Ready !")
    asynchronous.create_task(start_helper())


async def start_helper():
    APP = ParaT()
    global PTSession, Builder, ActiveTracker
    PTSession = await APP.initialize()
    # microservices
    Builder = PipelineBuilder(PTSession)
    ActiveTracker = ActiveObjects(PTSession, "ActiveSources")
    asynchronous.create_task(observe_active())
    asynchronous.create_task(observer_pipeline())


# -----------------------------------------------------------------------------
# Globals
# -----------------------------------------------------------------------------
Builder = None
ActiveTracker = None
PTSession = None


# -----------------------------------------------------------------------------
# Button slots
# -----------------------------------------------------------------------------


async def create_proxy(group, name):
    if group == "sources":
        await Builder.CreateSource(group, name)
    elif group == "filters":
        # Get active source
        proxy = await anext(ActiveTracker.GetCurrentObservable())
        await Builder.CreateFilter(group, name, proxy)
    else:
        print("Unknown proxy type")


def on_active_change(active):
    print(active)
    proxy = PTSession.GetProxyManager().FindProxy(int(active[0]))
    ActiveTracker.SetCurrentProxy(proxy, vtkSMProxySelectionModel.CLEAR)


async def on_action(event):
    print("on_action", event)
    _action = event.get("action")
    if _action == "delete":
        _id = int(event.get("id"))
        proxy = PTSession.GetProxyManager().FindProxy(_id)
        status = await Builder.DeleteProxy(proxy)
        print(f"Deleted: {status}")


# -----------------------------------------------------------------------------
async def observe_active():
    async for proxy in ActiveTracker.GetCurrentObservable():
        with state:
            if proxy:
                state.active_source = [str(proxy.GetGlobalID())]
                state.active_source_label = (
                    f"{proxy.GetLogName()} - gid {proxy.GetGlobalID()}"
                )

                pmanager = PropertyManager()
                status = await pmanager.UpdatePipeline(proxy)
                dataInformation = proxy.GetDataInformation(0)
                state.active_data_information = str(dataInformation)
            else:
                state.active_source = []
                state.active_source_label = "None"
                state.active_data_information = "None"
        # state.flush() // with state: replaces that


async def observer_pipeline():
    pipelineViewer = PipelineViewer(PTSession)
    root = {"name": "parat", "id": "1", "parent": "0", "color": "#000000", "visible": 0}
    # [{'name': 'root', 'visible': 0, 'collapsed': 0, 'id': '1', 'parent': '0', 'color': '#9C27B0', 'actions': ['test', 'delete']}]
    async for pipelineState in pipelineViewer.GetObservable():
        list_to_fill = [root]
        for item in pipelineState:
            node = {
                "name": item.GetName(),
                "parent": str(
                    item.GetParentIDs()[0] if len(item.GetParentIDs()) > 0 else 1
                ),
                "id": str(item.GetID()),
                "actions": ["delete"],
                "visibile": 1,
            }
            list_to_fill.append(node)
        with state:
            state.git_tree = list_to_fill


# -----------------------------------------------------------------------------
# UI setup
# -----------------------------------------------------------------------------
layout = SinglePageLayout(server)

from pathlib import Path

BASE = Path(__file__).parent

from trame.assets.local import LocalFileManager

local_file_manager = LocalFileManager(__file__)
local_file_manager.url("delete", BASE / "icons/trash-can-outline.svg")


with layout:
    with layout.toolbar as toolbar:
        toolbar.dense = True
        vuetify.VSpacer()

    with layout.content:
        trame.GitTree(
            sources=("git_tree",),
            actives=("active_source",),
            action_map=("icons", local_file_manager.assets),
            # visibility_change=(on_event, "[$event]"),
            action_size=25,
            action=(on_action, "[$event]"),
            actives_change=(on_active_change, "[$event]"),
        )
        html.H3("Create")
        vuetify.VBtn("Cone", click=(create_proxy, ["sources", "ConeSource"]))
        vuetify.VBtn("Wavelet", click=(create_proxy, ["sources", "RTAnalyticSource"]))
        vuetify.VBtn("Sphere", click=(create_proxy, ["sources", "SphereSource"]))
        vuetify.VBtn("Shrink", click=(create_proxy, ["filters", "ShrinkFilter"]))
        html.H3("Information")
        html.Pre(
            "ActiveSource: {{ active_source_label }}\n\n"
            "Data Information\n{{ active_data_information}}"
        )

# -----------------------------------------------------------------------------
# start server
# -----------------------------------------------------------------------------

if __name__ == "__main__":
    server.start()
