import enum
import typing
import uuid
from dataclasses import field

import marshmallow_dataclass
from marshmallow import EXCLUDE, pre_load

from te_schemas import SchemaBase


class AlgorithmRunMode(enum.Enum):
    NOT_APPLICABLE = 0
    LOCAL = "local"
    REMOTE = "remote"
    BOTH = "both"


@marshmallow_dataclass.dataclass
class ExecutionScript(SchemaBase):
    class Meta:
        unknown = EXCLUDE

    id: typing.Union[uuid.UUID, str]
    run_mode: typing.Optional[AlgorithmRunMode] = field(
        metadata={"by_value": True}, default=AlgorithmRunMode.NOT_APPLICABLE
    )
    name: typing.Optional[str] = field(default="")
    slug: typing.Optional[str] = field(default="")
    execution_callable: typing.Optional[str] = field(default="")
    version: typing.Optional[str] = field(default="")
    description: typing.Optional[str] = field(default="")
    name_readable: typing.Optional[str] = field(default="")
    additional_configuration: typing.Optional[dict] = None

    def __post_init__(self):  # ensure mutable default created safely
        if self.additional_configuration is None:
            self.additional_configuration = {}

    @pre_load
    def set_id_and_slug(self, data, **kwargs):
        if not data.get("slug"):
            data["slug"] = data.get("name", "").replace(" ", "-").lower()
            if data.get("version"):
                data["slug"] = data["slug"] + "-" + data["version"].replace(".", "-")
        if not data.get("id"):
            if data.get("name"):
                data["id"] = data.get("name")
            elif data.get("slug"):
                data["id"] = data.get("slug")
            else:
                data["id"] = "unknown-" + str(uuid.uuid4())

        return data
