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.attachment import Attachment
    from ..models.bound import Bound
    from ..models.document_aspects import DocumentAspects
    from ..models.document_canvas import DocumentCanvas
    from ..models.document_flag import DocumentFlag
    from ..models.document_job import DocumentJob
    from ..models.document_note import DocumentNote
    from ..models.document_provider import DocumentProvider
    from ..models.document_rotations import DocumentRotations
    from ..models.document_sharing import DocumentSharing
    from ..models.document_viewed import DocumentViewed
    from ..models.fillable import Fillable
    from ..models.metadata import Metadata
    from ..models.split import Split
    from ..models.sync_info import SyncInfo
    from ..models.table import Table
    from ..models.time_event import TimeEvent


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


@_attrs_define
class Document:
    """
    Attributes:
        field_id (str | Unset): MongoDB ObjectId
        team (str | Unset): MongoDB ObjectId
        stack (str | Unset): MongoDB ObjectId
        name (str | Unset):
        original_name (str | Unset):
        format_ (str | Unset):
        download (str | Unset):
        thumbnail (str | Unset):
        source (str | Unset):
        source_url (str | Unset):
        provider (DocumentProvider | Unset):
        import_key (str | Unset):
        pages (list[str] | Unset):
        rotations (DocumentRotations | Unset):
        aspects (DocumentAspects | Unset):
        job (DocumentJob | Unset):
        urgent (bool | Unset):
        deadline (datetime.datetime | Unset):
        flagged (bool | Unset):
        pinned (bool | Unset):
        flags (list[DocumentFlag] | Unset):
        reviewed (bool | Unset):
        archived (bool | Unset):
        assignee (str | Unset): MongoDB ObjectId
        sharing (DocumentSharing | Unset):
        checksum (str | Unset):
        metadata (list[Metadata] | Unset):
        fillable (Fillable | Unset):
        keywords (list[str] | Unset):
        bounds (list[Bound] | Unset):
        tables (list[Table] | Unset):
        split (list[Split] | Unset):
        notes (list[DocumentNote] | Unset):
        canvas (DocumentCanvas | Unset):
        bulk (bool | Unset):
        original (str | Unset): MongoDB ObjectId
        split_from (str | Unset): MongoDB ObjectId
        attachments (list[Attachment] | Unset):
        time (list[TimeEvent] | Unset):
        viewed (DocumentViewed | Unset):
        sync (list[SyncInfo] | Unset):
        received_on (datetime.datetime | Unset):
        last_modified (datetime.datetime | Unset):
        next_stack (str | Unset): MongoDB ObjectId
        sender (str | Unset):
    """

    field_id: str | Unset = UNSET
    team: str | Unset = UNSET
    stack: str | Unset = UNSET
    name: str | Unset = UNSET
    original_name: str | Unset = UNSET
    format_: str | Unset = UNSET
    download: str | Unset = UNSET
    thumbnail: str | Unset = UNSET
    source: str | Unset = UNSET
    source_url: str | Unset = UNSET
    provider: DocumentProvider | Unset = UNSET
    import_key: str | Unset = UNSET
    pages: list[str] | Unset = UNSET
    rotations: DocumentRotations | Unset = UNSET
    aspects: DocumentAspects | Unset = UNSET
    job: DocumentJob | Unset = UNSET
    urgent: bool | Unset = UNSET
    deadline: datetime.datetime | Unset = UNSET
    flagged: bool | Unset = UNSET
    pinned: bool | Unset = UNSET
    flags: list[DocumentFlag] | Unset = UNSET
    reviewed: bool | Unset = UNSET
    archived: bool | Unset = UNSET
    assignee: str | Unset = UNSET
    sharing: DocumentSharing | Unset = UNSET
    checksum: str | Unset = UNSET
    metadata: list[Metadata] | Unset = UNSET
    fillable: Fillable | Unset = UNSET
    keywords: list[str] | Unset = UNSET
    bounds: list[Bound] | Unset = UNSET
    tables: list[Table] | Unset = UNSET
    split: list[Split] | Unset = UNSET
    notes: list[DocumentNote] | Unset = UNSET
    canvas: DocumentCanvas | Unset = UNSET
    bulk: bool | Unset = UNSET
    original: str | Unset = UNSET
    split_from: str | Unset = UNSET
    attachments: list[Attachment] | Unset = UNSET
    time: list[TimeEvent] | Unset = UNSET
    viewed: DocumentViewed | Unset = UNSET
    sync: list[SyncInfo] | Unset = UNSET
    received_on: datetime.datetime | Unset = UNSET
    last_modified: datetime.datetime | Unset = UNSET
    next_stack: str | Unset = UNSET
    sender: 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

        team = self.team

        stack = self.stack

        name = self.name

        original_name = self.original_name

        format_ = self.format_

        download = self.download

        thumbnail = self.thumbnail

        source = self.source

        source_url = self.source_url

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

        import_key = self.import_key

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

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

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

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

        urgent = self.urgent

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

        flagged = self.flagged

        pinned = self.pinned

        flags: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.flags, Unset):
            flags = []
            for flags_item_data in self.flags:
                flags_item = flags_item_data.to_dict()
                flags.append(flags_item)

        reviewed = self.reviewed

        archived = self.archived

        assignee = self.assignee

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

        checksum = self.checksum

        metadata: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.metadata, Unset):
            metadata = []
            for metadata_item_data in self.metadata:
                metadata_item = metadata_item_data.to_dict()
                metadata.append(metadata_item)

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

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

        bounds: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.bounds, Unset):
            bounds = []
            for bounds_item_data in self.bounds:
                bounds_item = bounds_item_data.to_dict()
                bounds.append(bounds_item)

        tables: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.tables, Unset):
            tables = []
            for tables_item_data in self.tables:
                tables_item = tables_item_data.to_dict()
                tables.append(tables_item)

        split: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.split, Unset):
            split = []
            for split_item_data in self.split:
                split_item = split_item_data.to_dict()
                split.append(split_item)

        notes: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.notes, Unset):
            notes = []
            for notes_item_data in self.notes:
                notes_item = notes_item_data.to_dict()
                notes.append(notes_item)

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

        bulk = self.bulk

        original = self.original

        split_from = self.split_from

        attachments: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.attachments, Unset):
            attachments = []
            for attachments_item_data in self.attachments:
                attachments_item = attachments_item_data.to_dict()
                attachments.append(attachments_item)

        time: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.time, Unset):
            time = []
            for time_item_data in self.time:
                time_item = time_item_data.to_dict()
                time.append(time_item)

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

        sync: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.sync, Unset):
            sync = []
            for sync_item_data in self.sync:
                sync_item = sync_item_data.to_dict()
                sync.append(sync_item)

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

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

        next_stack = self.next_stack

        sender = self.sender

        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 team is not UNSET:
            field_dict["team"] = team
        if stack is not UNSET:
            field_dict["stack"] = stack
        if name is not UNSET:
            field_dict["name"] = name
        if original_name is not UNSET:
            field_dict["originalName"] = original_name
        if format_ is not UNSET:
            field_dict["format"] = format_
        if download is not UNSET:
            field_dict["download"] = download
        if thumbnail is not UNSET:
            field_dict["thumbnail"] = thumbnail
        if source is not UNSET:
            field_dict["source"] = source
        if source_url is not UNSET:
            field_dict["sourceUrl"] = source_url
        if provider is not UNSET:
            field_dict["provider"] = provider
        if import_key is not UNSET:
            field_dict["importKey"] = import_key
        if pages is not UNSET:
            field_dict["pages"] = pages
        if rotations is not UNSET:
            field_dict["rotations"] = rotations
        if aspects is not UNSET:
            field_dict["aspects"] = aspects
        if job is not UNSET:
            field_dict["job"] = job
        if urgent is not UNSET:
            field_dict["urgent"] = urgent
        if deadline is not UNSET:
            field_dict["deadline"] = deadline
        if flagged is not UNSET:
            field_dict["flagged"] = flagged
        if pinned is not UNSET:
            field_dict["pinned"] = pinned
        if flags is not UNSET:
            field_dict["flags"] = flags
        if reviewed is not UNSET:
            field_dict["reviewed"] = reviewed
        if archived is not UNSET:
            field_dict["archived"] = archived
        if assignee is not UNSET:
            field_dict["assignee"] = assignee
        if sharing is not UNSET:
            field_dict["sharing"] = sharing
        if checksum is not UNSET:
            field_dict["checksum"] = checksum
        if metadata is not UNSET:
            field_dict["metadata"] = metadata
        if fillable is not UNSET:
            field_dict["fillable"] = fillable
        if keywords is not UNSET:
            field_dict["keywords"] = keywords
        if bounds is not UNSET:
            field_dict["bounds"] = bounds
        if tables is not UNSET:
            field_dict["tables"] = tables
        if split is not UNSET:
            field_dict["split"] = split
        if notes is not UNSET:
            field_dict["notes"] = notes
        if canvas is not UNSET:
            field_dict["canvas"] = canvas
        if bulk is not UNSET:
            field_dict["bulk"] = bulk
        if original is not UNSET:
            field_dict["original"] = original
        if split_from is not UNSET:
            field_dict["splitFrom"] = split_from
        if attachments is not UNSET:
            field_dict["attachments"] = attachments
        if time is not UNSET:
            field_dict["time"] = time
        if viewed is not UNSET:
            field_dict["viewed"] = viewed
        if sync is not UNSET:
            field_dict["sync"] = sync
        if received_on is not UNSET:
            field_dict["receivedOn"] = received_on
        if last_modified is not UNSET:
            field_dict["lastModified"] = last_modified
        if next_stack is not UNSET:
            field_dict["nextStack"] = next_stack
        if sender is not UNSET:
            field_dict["sender"] = sender

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.attachment import Attachment
        from ..models.bound import Bound
        from ..models.document_aspects import DocumentAspects
        from ..models.document_canvas import DocumentCanvas
        from ..models.document_flag import DocumentFlag
        from ..models.document_job import DocumentJob
        from ..models.document_note import DocumentNote
        from ..models.document_provider import DocumentProvider
        from ..models.document_rotations import DocumentRotations
        from ..models.document_sharing import DocumentSharing
        from ..models.document_viewed import DocumentViewed
        from ..models.fillable import Fillable
        from ..models.metadata import Metadata
        from ..models.split import Split
        from ..models.sync_info import SyncInfo
        from ..models.table import Table
        from ..models.time_event import TimeEvent

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

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

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

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

        original_name = d.pop("originalName", UNSET)

        format_ = d.pop("format", UNSET)

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

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

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

        source_url = d.pop("sourceUrl", UNSET)

        _provider = d.pop("provider", UNSET)
        provider: DocumentProvider | Unset
        if isinstance(_provider, Unset):
            provider = UNSET
        else:
            provider = DocumentProvider.from_dict(_provider)

        import_key = d.pop("importKey", UNSET)

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

        _rotations = d.pop("rotations", UNSET)
        rotations: DocumentRotations | Unset
        if isinstance(_rotations, Unset):
            rotations = UNSET
        else:
            rotations = DocumentRotations.from_dict(_rotations)

        _aspects = d.pop("aspects", UNSET)
        aspects: DocumentAspects | Unset
        if isinstance(_aspects, Unset):
            aspects = UNSET
        else:
            aspects = DocumentAspects.from_dict(_aspects)

        _job = d.pop("job", UNSET)
        job: DocumentJob | Unset
        if isinstance(_job, Unset):
            job = UNSET
        else:
            job = DocumentJob.from_dict(_job)

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

        _deadline = d.pop("deadline", UNSET)
        deadline: datetime.datetime | Unset
        if isinstance(_deadline, Unset):
            deadline = UNSET
        else:
            deadline = isoparse(_deadline)

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

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

        _flags = d.pop("flags", UNSET)
        flags: list[DocumentFlag] | Unset = UNSET
        if _flags is not UNSET:
            flags = []
            for flags_item_data in _flags:
                flags_item = DocumentFlag.from_dict(flags_item_data)

                flags.append(flags_item)

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

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

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

        _sharing = d.pop("sharing", UNSET)
        sharing: DocumentSharing | Unset
        if isinstance(_sharing, Unset):
            sharing = UNSET
        else:
            sharing = DocumentSharing.from_dict(_sharing)

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

        _metadata = d.pop("metadata", UNSET)
        metadata: list[Metadata] | Unset = UNSET
        if _metadata is not UNSET:
            metadata = []
            for metadata_item_data in _metadata:
                metadata_item = Metadata.from_dict(metadata_item_data)

                metadata.append(metadata_item)

        _fillable = d.pop("fillable", UNSET)
        fillable: Fillable | Unset
        if isinstance(_fillable, Unset):
            fillable = UNSET
        else:
            fillable = Fillable.from_dict(_fillable)

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

        _bounds = d.pop("bounds", UNSET)
        bounds: list[Bound] | Unset = UNSET
        if _bounds is not UNSET:
            bounds = []
            for bounds_item_data in _bounds:
                bounds_item = Bound.from_dict(bounds_item_data)

                bounds.append(bounds_item)

        _tables = d.pop("tables", UNSET)
        tables: list[Table] | Unset = UNSET
        if _tables is not UNSET:
            tables = []
            for tables_item_data in _tables:
                tables_item = Table.from_dict(tables_item_data)

                tables.append(tables_item)

        _split = d.pop("split", UNSET)
        split: list[Split] | Unset = UNSET
        if _split is not UNSET:
            split = []
            for split_item_data in _split:
                split_item = Split.from_dict(split_item_data)

                split.append(split_item)

        _notes = d.pop("notes", UNSET)
        notes: list[DocumentNote] | Unset = UNSET
        if _notes is not UNSET:
            notes = []
            for notes_item_data in _notes:
                notes_item = DocumentNote.from_dict(notes_item_data)

                notes.append(notes_item)

        _canvas = d.pop("canvas", UNSET)
        canvas: DocumentCanvas | Unset
        if isinstance(_canvas, Unset):
            canvas = UNSET
        else:
            canvas = DocumentCanvas.from_dict(_canvas)

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

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

        split_from = d.pop("splitFrom", UNSET)

        _attachments = d.pop("attachments", UNSET)
        attachments: list[Attachment] | Unset = UNSET
        if _attachments is not UNSET:
            attachments = []
            for attachments_item_data in _attachments:
                attachments_item = Attachment.from_dict(attachments_item_data)

                attachments.append(attachments_item)

        _time = d.pop("time", UNSET)
        time: list[TimeEvent] | Unset = UNSET
        if _time is not UNSET:
            time = []
            for time_item_data in _time:
                time_item = TimeEvent.from_dict(time_item_data)

                time.append(time_item)

        _viewed = d.pop("viewed", UNSET)
        viewed: DocumentViewed | Unset
        if isinstance(_viewed, Unset):
            viewed = UNSET
        else:
            viewed = DocumentViewed.from_dict(_viewed)

        _sync = d.pop("sync", UNSET)
        sync: list[SyncInfo] | Unset = UNSET
        if _sync is not UNSET:
            sync = []
            for sync_item_data in _sync:
                sync_item = SyncInfo.from_dict(sync_item_data)

                sync.append(sync_item)

        _received_on = d.pop("receivedOn", UNSET)
        received_on: datetime.datetime | Unset
        if isinstance(_received_on, Unset):
            received_on = UNSET
        else:
            received_on = isoparse(_received_on)

        _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)

        next_stack = d.pop("nextStack", UNSET)

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

        document = cls(
            field_id=field_id,
            team=team,
            stack=stack,
            name=name,
            original_name=original_name,
            format_=format_,
            download=download,
            thumbnail=thumbnail,
            source=source,
            source_url=source_url,
            provider=provider,
            import_key=import_key,
            pages=pages,
            rotations=rotations,
            aspects=aspects,
            job=job,
            urgent=urgent,
            deadline=deadline,
            flagged=flagged,
            pinned=pinned,
            flags=flags,
            reviewed=reviewed,
            archived=archived,
            assignee=assignee,
            sharing=sharing,
            checksum=checksum,
            metadata=metadata,
            fillable=fillable,
            keywords=keywords,
            bounds=bounds,
            tables=tables,
            split=split,
            notes=notes,
            canvas=canvas,
            bulk=bulk,
            original=original,
            split_from=split_from,
            attachments=attachments,
            time=time,
            viewed=viewed,
            sync=sync,
            received_on=received_on,
            last_modified=last_modified,
            next_stack=next_stack,
            sender=sender,
        )

        document.additional_properties = d
        return document

    @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
