# 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 pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List
from airflow_client.client.models.app_builder_menu_item_response import AppBuilderMenuItemResponse
from airflow_client.client.models.app_builder_view_response import AppBuilderViewResponse
from airflow_client.client.models.external_view_response import ExternalViewResponse
from airflow_client.client.models.fast_api_app_response import FastAPIAppResponse
from airflow_client.client.models.fast_api_root_middleware_response import FastAPIRootMiddlewareResponse
from airflow_client.client.models.react_app_response import ReactAppResponse
from typing import Optional, Set
from typing_extensions import Self
from pydantic_core import to_jsonable_python

class PluginResponse(BaseModel):
    """
    Plugin serializer.
    """ # noqa: E501
    appbuilder_menu_items: List[AppBuilderMenuItemResponse]
    appbuilder_views: List[AppBuilderViewResponse]
    external_views: List[ExternalViewResponse] = Field(description="Aggregate all external views. Both 'external_views' and 'appbuilder_menu_items' are included here.")
    fastapi_apps: List[FastAPIAppResponse]
    fastapi_root_middlewares: List[FastAPIRootMiddlewareResponse]
    flask_blueprints: List[StrictStr]
    global_operator_extra_links: List[StrictStr]
    listeners: List[StrictStr]
    macros: List[StrictStr]
    name: StrictStr
    operator_extra_links: List[StrictStr]
    react_apps: List[ReactAppResponse]
    source: StrictStr
    timetables: List[StrictStr]
    __properties: ClassVar[List[str]] = ["appbuilder_menu_items", "appbuilder_views", "external_views", "fastapi_apps", "fastapi_root_middlewares", "flask_blueprints", "global_operator_extra_links", "listeners", "macros", "name", "operator_extra_links", "react_apps", "source", "timetables"]

    model_config = ConfigDict(
        validate_by_name=True,
        validate_by_alias=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"""
        return json.dumps(to_jsonable_python(self.to_dict()))

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of PluginResponse 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 appbuilder_menu_items (list)
        _items = []
        if self.appbuilder_menu_items:
            for _item_appbuilder_menu_items in self.appbuilder_menu_items:
                if _item_appbuilder_menu_items:
                    _items.append(_item_appbuilder_menu_items.to_dict())
            _dict['appbuilder_menu_items'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in appbuilder_views (list)
        _items = []
        if self.appbuilder_views:
            for _item_appbuilder_views in self.appbuilder_views:
                if _item_appbuilder_views:
                    _items.append(_item_appbuilder_views.to_dict())
            _dict['appbuilder_views'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in external_views (list)
        _items = []
        if self.external_views:
            for _item_external_views in self.external_views:
                if _item_external_views:
                    _items.append(_item_external_views.to_dict())
            _dict['external_views'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in fastapi_apps (list)
        _items = []
        if self.fastapi_apps:
            for _item_fastapi_apps in self.fastapi_apps:
                if _item_fastapi_apps:
                    _items.append(_item_fastapi_apps.to_dict())
            _dict['fastapi_apps'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in fastapi_root_middlewares (list)
        _items = []
        if self.fastapi_root_middlewares:
            for _item_fastapi_root_middlewares in self.fastapi_root_middlewares:
                if _item_fastapi_root_middlewares:
                    _items.append(_item_fastapi_root_middlewares.to_dict())
            _dict['fastapi_root_middlewares'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in react_apps (list)
        _items = []
        if self.react_apps:
            for _item_react_apps in self.react_apps:
                if _item_react_apps:
                    _items.append(_item_react_apps.to_dict())
            _dict['react_apps'] = _items
        return _dict

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

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

        _obj = cls.model_validate({
            "appbuilder_menu_items": [AppBuilderMenuItemResponse.from_dict(_item) for _item in obj["appbuilder_menu_items"]] if obj.get("appbuilder_menu_items") is not None else None,
            "appbuilder_views": [AppBuilderViewResponse.from_dict(_item) for _item in obj["appbuilder_views"]] if obj.get("appbuilder_views") is not None else None,
            "external_views": [ExternalViewResponse.from_dict(_item) for _item in obj["external_views"]] if obj.get("external_views") is not None else None,
            "fastapi_apps": [FastAPIAppResponse.from_dict(_item) for _item in obj["fastapi_apps"]] if obj.get("fastapi_apps") is not None else None,
            "fastapi_root_middlewares": [FastAPIRootMiddlewareResponse.from_dict(_item) for _item in obj["fastapi_root_middlewares"]] if obj.get("fastapi_root_middlewares") is not None else None,
            "flask_blueprints": obj.get("flask_blueprints"),
            "global_operator_extra_links": obj.get("global_operator_extra_links"),
            "listeners": obj.get("listeners"),
            "macros": obj.get("macros"),
            "name": obj.get("name"),
            "operator_extra_links": obj.get("operator_extra_links"),
            "react_apps": [ReactAppResponse.from_dict(_item) for _item in obj["react_apps"]] if obj.get("react_apps") is not None else None,
            "source": obj.get("source"),
            "timetables": obj.get("timetables")
        })
        return _obj


