"""Paste this entry into a Rhino 8 Grasshopper Python 3 component.

Inputs: AdapterRoot (repo root path), BaseUrl, ApiKey (optional text), ProjectId,
ModelId, IdempotencyKey (stable >=8 chars), Receive (bool), Poll (bool),
Preview (bool), Bake (bool), ContinueBake (bool), Cancel (bool),
RestoreOrigin (bool, default False), BatchSize (integer, default 100).
Outputs: Geometry, IDs, Metadata, Report, JobId, RhinoIDs.

Use momentary buttons or toggle false between explicit triggers. API key may be
provided by owner's authorized ApiKey text input or ONTOLOGIC_API_KEY environment.
"""
import sys
import json
import Rhino
import scriptcontext as sc
if AdapterRoot not in sys.path:
    sys.path.insert(0,AdapterRoot)
from adapters.ifc_to_rhino.client import ReceiveClient
from adapters.ifc_to_rhino.rhino import BakeSession,preview

Geometry=[];IDs=[];Metadata=None;Report={};JobId=None;RhinoIDs=[]
slot="Ontologic.IFC.Receive."+str(ghenv.Component.InstanceGuid)
state=sc.sticky.setdefault(slot,{"edges":{}})
try:
    flags={"receive":bool(Receive),"poll":bool(Poll),"bake":bool(Bake),"continue":bool(ContinueBake),"cancel":bool(Cancel)}
    rising=dict((k,v and not state["edges"].get(k,False)) for k,v in flags.items())
    state["edges"]=flags
    client=ReceiveClient(BaseUrl,ApiKey)
    if rising["receive"]:
        if not IdempotencyKey:
            raise ValueError("Provide a stable IdempotencyKey for this revision.")
        state["job"]=client.start(ProjectId,ModelId,IdempotencyKey)
        state.pop("package",None);state.pop("bake",None)
    job=state.get("job")
    if job:
        JobId=job["jobId"]
    if rising["cancel"]:
        if state.get("bake"):
            Report=state["bake"].advance(cancel=True)
        if job and job["state"] in ("queued","running"):
            state["job"]=client.control(ProjectId,ModelId,JobId,"cancel")
    if rising["poll"] and job:
        state["job"]=client.status(ProjectId,ModelId,JobId)
        if state["job"]["state"]=="succeeded" and "package" not in state:
            state["package"]=client.receive(ProjectId,ModelId,JobId)
    package=state.get("package")
    if package:
        directory,manifest,metadata=package
        IDs=[o["id"] for o in manifest["occurrences"]]
        Metadata=metadata
        Report=dict(manifest["report"],previewLimit=2000)
        if Preview:
            Geometry,_=preview(manifest,directory,Rhino.RhinoDoc.ActiveDoc,2000,bool(RestoreOrigin))
        if rising["bake"]:
            state["bake"]=BakeSession(manifest,metadata,directory,Rhino.RhinoDoc.ActiveDoc,bool(RestoreOrigin),BatchSize or 100)
        if rising["bake"] or rising["continue"]:
            if not state.get("bake"):
                raise ValueError("Receive a package and trigger Bake first.")
            Report=state["bake"].advance()
            RhinoIDs=Report.get("rhinoIds",[])
    elif state.get("job"):
        Report=state["job"]
except Exception as error:
    # Safe adapter codes only; do not render arbitrary response/credential contents.
    Report={"state":"error","code":str(error) if isinstance(error,(ValueError,RuntimeError)) else "adapter_failed"}
