from base64 import urlsafe_b64decode
from cerberus import Validator
from tempfile import mktemp
from pathlib import Path
import azure.durable_functions as df
import logging
import os


schema = {
    "steps": {
        "type": "list",
        "required": True,
        "schema": {
            "type": "dict",
            "schema": {
                "name": {
                    "type": "string",
                    "required": True,
                },
                "code": {
                    "type": "string",
                    "required": True,
                },
                "sources": {
                    "type": "dict",
                    "required": True,
                    "schema": {
                        "same.yaml": {
                            "type": "string",
                            "required": True,
                        },
                        "requirements.txt": {
                            "type": "string",
                            "required": False,
                        }
                    }
                },
            },
        },
    },
}


def info(msg: str):
    logging.info(f"orchestrator: {msg}")


# TODO: pass through a GUID generated by initiator for consistent logging.
def _orchestrator(context: df.DurableOrchestrationContext):
    """Orchestrates the execution of a pipeline's SAME steps."""
    input = context.get_input()
    if input is None:  # should never happen, it's only triggered by us
        raise Exception("no input provided to orchestrator.")

    validator = Validator(schema)
    if not validator.validate(input):
        raise SyntaxError(f"input is invalid: {validator.errors}")

    session_context = None
    for step in input["steps"]:
        result = yield context.call_activity("executor", {
            "step": step,
            "session_context": session_context,
        })

        # Propagate resulting session context to the next execution step:
        session_context = result["session_context"]

    return result

orchestrator = df.Orchestrator.create(_orchestrator)
