# coding: utf-8

"""
    Airflow API

    Airflow API. All endpoints located under ``/api/v2`` can be used safely, are stable and backward compatible. Endpoints located under ``/ui`` are dedicated to the UI and are subject to breaking change depending on the need of the frontend. Users should not rely on those but use the public ones instead.

    The version of the OpenAPI document: 2
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from datetime import datetime
from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from airflow_client.client.models.asset_alias_response import AssetAliasResponse
from airflow_client.client.models.dag_schedule_asset_reference import DagScheduleAssetReference
from airflow_client.client.models.last_asset_event_response import LastAssetEventResponse
from airflow_client.client.models.task_inlet_asset_reference import TaskInletAssetReference
from airflow_client.client.models.task_outlet_asset_reference import TaskOutletAssetReference
from typing import Optional, Set
from typing_extensions import Self

class AssetResponse(BaseModel):
    """
    Asset serializer for responses.
    """ # noqa: E501
    aliases: List[AssetAliasResponse]
    consuming_tasks: List[TaskInletAssetReference]
    created_at: datetime
    extra: Optional[Dict[str, Any]] = None
    group: StrictStr
    id: StrictInt
    last_asset_event: Optional[LastAssetEventResponse] = None
    name: StrictStr
    producing_tasks: List[TaskOutletAssetReference]
    scheduled_dags: List[DagScheduleAssetReference]
    updated_at: datetime
    uri: StrictStr
    __properties: ClassVar[List[str]] = ["aliases", "consuming_tasks", "created_at", "extra", "group", "id", "last_asset_event", "name", "producing_tasks", "scheduled_dags", "updated_at", "uri"]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of AssetResponse from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of each item in aliases (list)
        _items = []
        if self.aliases:
            for _item_aliases in self.aliases:
                if _item_aliases:
                    _items.append(_item_aliases.to_dict())
            _dict['aliases'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in consuming_tasks (list)
        _items = []
        if self.consuming_tasks:
            for _item_consuming_tasks in self.consuming_tasks:
                if _item_consuming_tasks:
                    _items.append(_item_consuming_tasks.to_dict())
            _dict['consuming_tasks'] = _items
        # override the default output from pydantic by calling `to_dict()` of last_asset_event
        if self.last_asset_event:
            _dict['last_asset_event'] = self.last_asset_event.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in producing_tasks (list)
        _items = []
        if self.producing_tasks:
            for _item_producing_tasks in self.producing_tasks:
                if _item_producing_tasks:
                    _items.append(_item_producing_tasks.to_dict())
            _dict['producing_tasks'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in scheduled_dags (list)
        _items = []
        if self.scheduled_dags:
            for _item_scheduled_dags in self.scheduled_dags:
                if _item_scheduled_dags:
                    _items.append(_item_scheduled_dags.to_dict())
            _dict['scheduled_dags'] = _items
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of AssetResponse from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "aliases": [AssetAliasResponse.from_dict(_item) for _item in obj["aliases"]] if obj.get("aliases") is not None else None,
            "consuming_tasks": [TaskInletAssetReference.from_dict(_item) for _item in obj["consuming_tasks"]] if obj.get("consuming_tasks") is not None else None,
            "created_at": obj.get("created_at"),
            "extra": obj.get("extra"),
            "group": obj.get("group"),
            "id": obj.get("id"),
            "last_asset_event": LastAssetEventResponse.from_dict(obj["last_asset_event"]) if obj.get("last_asset_event") is not None else None,
            "name": obj.get("name"),
            "producing_tasks": [TaskOutletAssetReference.from_dict(_item) for _item in obj["producing_tasks"]] if obj.get("producing_tasks") is not None else None,
            "scheduled_dags": [DagScheduleAssetReference.from_dict(_item) for _item in obj["scheduled_dags"]] if obj.get("scheduled_dags") is not None else None,
            "updated_at": obj.get("updated_at"),
            "uri": obj.get("uri")
        })
        return _obj


