from __future__ import annotations

import datetime
from collections.abc import Mapping
from typing import TYPE_CHECKING, Any, TypeVar, cast

from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse

from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.data_type import DataType
    from ..models.pipeline_module import PipelineModule
    from ..models.stack_rules import StackRules
    from ..models.trainer import Trainer


T = TypeVar("T", bound="Stack")


@_attrs_define
class Stack:
    """
    Attributes:
        field_id (str | Unset): MongoDB ObjectId
        path (str | Unset):
        template (str | Unset): MongoDB ObjectId
        team (str | Unset): MongoDB ObjectId
        base_name (str | Unset):
        base (str | Unset): MongoDB ObjectId
        restrict (bool | Unset):
        access (list[str] | Unset):
        pinned (bool | Unset):
        hide_hint (bool | Unset):
        enabled (bool | Unset):
        last_modified (datetime.datetime | Unset):
        num_documents (float | Unset):
        num_unread (float | Unset):
        keys (list[str] | Unset):
        data_types (list[DataType] | Unset):
        rules (StackRules | Unset):
        trainer (Trainer | Unset):
        num_moved_files (float | Unset):
        pipeline (list[PipelineModule] | Unset):
        locked (bool | Unset):
        forms (list[str] | Unset):
        tags (list[str] | Unset):
    """

    field_id: str | Unset = UNSET
    path: str | Unset = UNSET
    template: str | Unset = UNSET
    team: str | Unset = UNSET
    base_name: str | Unset = UNSET
    base: str | Unset = UNSET
    restrict: bool | Unset = UNSET
    access: list[str] | Unset = UNSET
    pinned: bool | Unset = UNSET
    hide_hint: bool | Unset = UNSET
    enabled: bool | Unset = UNSET
    last_modified: datetime.datetime | Unset = UNSET
    num_documents: float | Unset = UNSET
    num_unread: float | Unset = UNSET
    keys: list[str] | Unset = UNSET
    data_types: list[DataType] | Unset = UNSET
    rules: StackRules | Unset = UNSET
    trainer: Trainer | Unset = UNSET
    num_moved_files: float | Unset = UNSET
    pipeline: list[PipelineModule] | Unset = UNSET
    locked: bool | Unset = UNSET
    forms: list[str] | Unset = UNSET
    tags: list[str] | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        field_id = self.field_id

        path = self.path

        template = self.template

        team = self.team

        base_name = self.base_name

        base = self.base

        restrict = self.restrict

        access: list[str] | Unset = UNSET
        if not isinstance(self.access, Unset):
            access = self.access

        pinned = self.pinned

        hide_hint = self.hide_hint

        enabled = self.enabled

        last_modified: str | Unset = UNSET
        if not isinstance(self.last_modified, Unset):
            last_modified = self.last_modified.isoformat()

        num_documents = self.num_documents

        num_unread = self.num_unread

        keys: list[str] | Unset = UNSET
        if not isinstance(self.keys, Unset):
            keys = self.keys

        data_types: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.data_types, Unset):
            data_types = []
            for data_types_item_data in self.data_types:
                data_types_item = data_types_item_data.to_dict()
                data_types.append(data_types_item)

        rules: dict[str, Any] | Unset = UNSET
        if not isinstance(self.rules, Unset):
            rules = self.rules.to_dict()

        trainer: dict[str, Any] | Unset = UNSET
        if not isinstance(self.trainer, Unset):
            trainer = self.trainer.to_dict()

        num_moved_files = self.num_moved_files

        pipeline: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.pipeline, Unset):
            pipeline = []
            for pipeline_item_data in self.pipeline:
                pipeline_item = pipeline_item_data.to_dict()
                pipeline.append(pipeline_item)

        locked = self.locked

        forms: list[str] | Unset = UNSET
        if not isinstance(self.forms, Unset):
            forms = self.forms

        tags: list[str] | Unset = UNSET
        if not isinstance(self.tags, Unset):
            tags = self.tags

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update({})
        if field_id is not UNSET:
            field_dict["_id"] = field_id
        if path is not UNSET:
            field_dict["path"] = path
        if template is not UNSET:
            field_dict["template"] = template
        if team is not UNSET:
            field_dict["team"] = team
        if base_name is not UNSET:
            field_dict["baseName"] = base_name
        if base is not UNSET:
            field_dict["base"] = base
        if restrict is not UNSET:
            field_dict["restrict"] = restrict
        if access is not UNSET:
            field_dict["access"] = access
        if pinned is not UNSET:
            field_dict["pinned"] = pinned
        if hide_hint is not UNSET:
            field_dict["hideHint"] = hide_hint
        if enabled is not UNSET:
            field_dict["enabled"] = enabled
        if last_modified is not UNSET:
            field_dict["lastModified"] = last_modified
        if num_documents is not UNSET:
            field_dict["numDocuments"] = num_documents
        if num_unread is not UNSET:
            field_dict["numUnread"] = num_unread
        if keys is not UNSET:
            field_dict["keys"] = keys
        if data_types is not UNSET:
            field_dict["dataTypes"] = data_types
        if rules is not UNSET:
            field_dict["rules"] = rules
        if trainer is not UNSET:
            field_dict["trainer"] = trainer
        if num_moved_files is not UNSET:
            field_dict["numMovedFiles"] = num_moved_files
        if pipeline is not UNSET:
            field_dict["pipeline"] = pipeline
        if locked is not UNSET:
            field_dict["locked"] = locked
        if forms is not UNSET:
            field_dict["forms"] = forms
        if tags is not UNSET:
            field_dict["tags"] = tags

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.data_type import DataType
        from ..models.pipeline_module import PipelineModule
        from ..models.stack_rules import StackRules
        from ..models.trainer import Trainer

        d = dict(src_dict)
        field_id = d.pop("_id", UNSET)

        path = d.pop("path", UNSET)

        template = d.pop("template", UNSET)

        team = d.pop("team", UNSET)

        base_name = d.pop("baseName", UNSET)

        base = d.pop("base", UNSET)

        restrict = d.pop("restrict", UNSET)

        access = cast(list[str], d.pop("access", UNSET))

        pinned = d.pop("pinned", UNSET)

        hide_hint = d.pop("hideHint", UNSET)

        enabled = d.pop("enabled", UNSET)

        _last_modified = d.pop("lastModified", UNSET)
        last_modified: datetime.datetime | Unset
        if isinstance(_last_modified, Unset):
            last_modified = UNSET
        else:
            last_modified = isoparse(_last_modified)

        num_documents = d.pop("numDocuments", UNSET)

        num_unread = d.pop("numUnread", UNSET)

        keys = cast(list[str], d.pop("keys", UNSET))

        _data_types = d.pop("dataTypes", UNSET)
        data_types: list[DataType] | Unset = UNSET
        if _data_types is not UNSET:
            data_types = []
            for data_types_item_data in _data_types:
                data_types_item = DataType.from_dict(data_types_item_data)

                data_types.append(data_types_item)

        _rules = d.pop("rules", UNSET)
        rules: StackRules | Unset
        if isinstance(_rules, Unset):
            rules = UNSET
        else:
            rules = StackRules.from_dict(_rules)

        _trainer = d.pop("trainer", UNSET)
        trainer: Trainer | Unset
        if isinstance(_trainer, Unset):
            trainer = UNSET
        else:
            trainer = Trainer.from_dict(_trainer)

        num_moved_files = d.pop("numMovedFiles", UNSET)

        _pipeline = d.pop("pipeline", UNSET)
        pipeline: list[PipelineModule] | Unset = UNSET
        if _pipeline is not UNSET:
            pipeline = []
            for pipeline_item_data in _pipeline:
                pipeline_item = PipelineModule.from_dict(pipeline_item_data)

                pipeline.append(pipeline_item)

        locked = d.pop("locked", UNSET)

        forms = cast(list[str], d.pop("forms", UNSET))

        tags = cast(list[str], d.pop("tags", UNSET))

        stack = cls(
            field_id=field_id,
            path=path,
            template=template,
            team=team,
            base_name=base_name,
            base=base,
            restrict=restrict,
            access=access,
            pinned=pinned,
            hide_hint=hide_hint,
            enabled=enabled,
            last_modified=last_modified,
            num_documents=num_documents,
            num_unread=num_unread,
            keys=keys,
            data_types=data_types,
            rules=rules,
            trainer=trainer,
            num_moved_files=num_moved_files,
            pipeline=pipeline,
            locked=locked,
            forms=forms,
            tags=tags,
        )

        stack.additional_properties = d
        return stack

    @property
    def additional_keys(self) -> list[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties
