import logging
from typing import Optional
from typing import Union

from twisted.internet.defer import Deferred
from twisted.internet.defer import inlineCallbacks
from vortex.Payload import Payload
from vortex.TupleSelector import TupleSelector
from vortex.handler.TupleDataObservableHandler import TuplesProviderABC

from peek_plugin_diagram._private.client.controller.GridCacheController import (
    GridCacheController,
)
from peek_plugin_diagram._private.storage.ModelSet import makeDispGroupGridKey
from peek_plugin_diagram._private.tuples.GroupDispsTuple import GroupDispsTuple
from peek_plugin_diagram._private.tuples.grid.EncodedGridTuple import (
    EncodedGridTuple,
)

logger = logging.getLogger(__name__)


class ClientGroupDispsTupleProvider(TuplesProviderABC):
    def __init__(self, gridCacheController: GridCacheController):
        self.gridCacheController = gridCacheController

    @inlineCallbacks
    def makeVortexMsg(
        self, filt: dict, tupleSelector: TupleSelector
    ) -> Union[Deferred, bytes]:
        coordSetId = tupleSelector.selector["coordSetId"]
        gridKey = makeDispGroupGridKey(coordSetId)
        grid: Optional[
            EncodedGridTuple
        ] = self.gridCacheController.encodedChunk(gridKey)

        groupDispTuple = GroupDispsTuple()
        groupDispTuple.coordSetId = coordSetId
        groupDispTuple.encodedGridTuple = (
            grid.encodedGridTuple if grid else None
        )

        payloadEnvelope = yield Payload(
            filt, tuples=[groupDispTuple]
        ).makePayloadEnvelopeDefer()

        vortexMsg = yield payloadEnvelope.toVortexMsgDefer()
        return vortexMsg
