# Public endpoint discovery and orientation checks shared by circulation components.
from dataclasses import dataclass
from hearth import Frame, Binding, ContractError
from hearth.kernel import Capability, Contract, Plan, Rule


@dataclass(frozen=True)
class Endpoint:
    host: str
    port: str

    def binding(self):
        return Binding(self.host, self.port, 'connect')

    def resolve(self, ctx):
        port = ctx.view.port(self.host, self.port)
        if port.kind not in ('access', 'public-access'):
            raise ContractError('endpoint-kind', ctx.path, port.frame.origin, 'Require an access or public-access port')
        at = ctx.local(port.frame.origin)
        turn = (port.frame.turn - ctx.frame.turn) % 4
        outward = Frame(turn=turn).vector((0, 0, -1))
        return port, at, (outward[0], outward[2])


@dataclass(frozen=True)
class EndpointContact:
    endpoint: Endpoint

    def capability(self):
        return Capability('extension.endpoint-contact', ('connection',), guarantees=('unchanged supported endpoint',))

    def negotiate(self, ctx, parameters):
        port, at, direction = self.endpoint.resolve(ctx)
        from hearth.space import Box
        return Contract(Box(at, at).expand(1), rules=(Rule('support', ((at[0], at[1] - 1, at[2]),)), Rule('clear', (at, (at[0], at[1] + 1, at[2])))))

    def realize(self, ctx, contract):
        return Plan()
