# coding: utf-8

"""
    Kubernetes

    No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)

    The version of the OpenAPI document: release-1.37
    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 collections.abc import Mapping as _Mapping
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, cast as _cast
from kubernetes.aio.client.models.v1_attached_volume import V1AttachedVolume
from kubernetes.aio.client.models.v1_container_image import V1ContainerImage
from kubernetes.aio.client.models.v1_node_address import V1NodeAddress
from kubernetes.aio.client.models.v1_node_condition import V1NodeCondition
from kubernetes.aio.client.models.v1_node_config_status import V1NodeConfigStatus
from kubernetes.aio.client.models.v1_node_daemon_endpoints import V1NodeDaemonEndpoints
from kubernetes.aio.client.models.v1_node_features import V1NodeFeatures
from kubernetes.aio.client.models.v1_node_runtime_handler import V1NodeRuntimeHandler
from kubernetes.aio.client.models.v1_node_system_info import V1NodeSystemInfo
from typing import Optional, Set
from typing_extensions import Self
from pydantic_core import to_jsonable_python


_OPENAPI_GENERATOR_TO_DICT = "_openapi_generator_to_dict"


def _get_openapi_to_dict(value: Any) -> Any:
    # Reciprocal function references preserve inherited generated methods
    # without reserving model member names. Checking both directions also
    # rejects overrides whose decorators copy function attributes.
    to_dict = getattr(value, "to_dict", None)
    type_to_dict = getattr(type(value), "to_dict", None)
    if (
        not callable(to_dict)
        or getattr(to_dict, "__func__", None) is not type_to_dict
    ):
        return None

    openapi_to_dict = getattr(
        type_to_dict, _OPENAPI_GENERATOR_TO_DICT, None
    )
    if (
        not callable(openapi_to_dict)
        or getattr(
            openapi_to_dict,
            _OPENAPI_GENERATOR_TO_DICT,
            None,
        ) is not type_to_dict
    ):
        return None
    return openapi_to_dict


def _to_legacy_item(value: Any, serialize: bool) -> Any:
    to_dict = getattr(value, "to_dict", None)
    if _get_openapi_to_dict(value) is not None and callable(to_dict):
        return to_dict(serialize=serialize)
    if callable(to_dict):
        return to_dict()
    return value


def _to_legacy_value(value: Any, serialize: bool) -> Any:
    # python-legacy converted only immediate list elements or dictionary values:
    # https://github.com/OpenAPITools/openapi-generator/blob/c84b949df1a9ec04ba75989cb49b45c940c2f694/modules/openapi-generator/src/main/resources/python-legacy/model.mustache#L203-L231
    if isinstance(value, list):
        return [_to_legacy_item(item, serialize) for item in value]
    if isinstance(value, dict):
        return {
            key: _to_legacy_item(item, serialize)
            for key, item in value.items()
        }
    return _to_legacy_item(value, serialize)


def _to_openapi_value(value: Any) -> Any:
    if isinstance(value, list):
        return [_to_openapi_value(item) for item in value]
    if isinstance(value, dict):
        return {key: _to_openapi_value(item) for key, item in value.items()}

    to_openapi_dict = _get_openapi_to_dict(value)
    if to_openapi_dict is not None:
        return to_openapi_dict(value)

    to_dict = getattr(value, "to_dict", None)
    if callable(to_dict):
        return to_dict()
    return value


class V1NodeStatus(BaseModel):
    """
    NodeStatus is information about the current status of a node.

    Attributes:
      openapi_types (dict): The key is attribute name
                            and the value is attribute type.
      attribute_map (dict): The key is attribute name
                            and the value is json key in definition.
    """ # noqa: E501
    addresses: Optional[List[V1NodeAddress]] = Field(default=None, description="List of addresses reachable to the node. Queried from cloud provider, if available. More info: https://kubernetes.io/docs/reference/node/node-status/#addresses Note: This field is declared as mergeable, but the merge key is not sufficiently unique, which can cause data corruption when it is merged. Callers should instead use a full-replacement patch. See https://pr.k8s.io/79391 for an example. Consumers should assume that addresses can change during the lifetime of a Node. However, there are some exceptions where this may not be possible, such as Pods that inherit a Node's address in its own status or consumers of the downward API (status.hostIP).")
    allocatable: Optional[Dict[str, StrictStr]] = Field(default=None, description="Allocatable represents the resources of a node that are available for scheduling. Defaults to Capacity.")
    capacity: Optional[Dict[str, StrictStr]] = Field(default=None, description="Capacity represents the total resources of a node. More info: https://kubernetes.io/docs/reference/node/node-status/#capacity")
    conditions: Optional[List[V1NodeCondition]] = Field(default=None, description="Conditions is an array of current observed node conditions. More info: https://kubernetes.io/docs/reference/node/node-status/#condition")
    config: Optional[V1NodeConfigStatus] = None
    daemon_endpoints: Optional[V1NodeDaemonEndpoints] = Field(default=None, validation_alias=AliasChoices("daemonEndpoints", "daemon_endpoints"), serialization_alias="daemonEndpoints")
    declared_features: Optional[List[StrictStr]] = Field(default=None, validation_alias=AliasChoices("declaredFeatures", "declared_features"), serialization_alias="declaredFeatures", description="DeclaredFeatures represents the features related to feature gates that are declared by the node.")
    features: Optional[V1NodeFeatures] = None
    images: Optional[List[V1ContainerImage]] = Field(default=None, description="List of container images on this node")
    node_info: Optional[V1NodeSystemInfo] = Field(default=None, validation_alias=AliasChoices("nodeInfo", "node_info"), serialization_alias="nodeInfo")
    phase: Optional[StrictStr] = Field(default=None, description="NodePhase is the recently observed lifecycle phase of the node. More info: https://kubernetes.io/docs/concepts/nodes/node/#phase The field is never populated, and now is deprecated.")
    runtime_handlers: Optional[List[V1NodeRuntimeHandler]] = Field(default=None, validation_alias=AliasChoices("runtimeHandlers", "runtime_handlers"), serialization_alias="runtimeHandlers", description="The available runtime handlers.")
    volumes_attached: Optional[List[V1AttachedVolume]] = Field(default=None, validation_alias=AliasChoices("volumesAttached", "volumes_attached"), serialization_alias="volumesAttached", description="List of volumes that are attached to the node.")
    volumes_in_use: Optional[List[StrictStr]] = Field(default=None, validation_alias=AliasChoices("volumesInUse", "volumes_in_use"), serialization_alias="volumesInUse", description="List of attachable volumes in use (mounted) by the node.")
    openapi_types: ClassVar[Dict[str, str]] = {
        "addresses": "List[V1NodeAddress]",
        "allocatable": "Dict[str, str]",
        "capacity": "Dict[str, str]",
        "conditions": "List[V1NodeCondition]",
        "config": "V1NodeConfigStatus",
        "daemon_endpoints": "V1NodeDaemonEndpoints",
        "declared_features": "List[str]",
        "features": "V1NodeFeatures",
        "images": "List[V1ContainerImage]",
        "node_info": "V1NodeSystemInfo",
        "phase": "str",
        "runtime_handlers": "List[V1NodeRuntimeHandler]",
        "volumes_attached": "List[V1AttachedVolume]",
        "volumes_in_use": "List[str]"
    }

    attribute_map: ClassVar[Dict[str, str]] = {
        "addresses": "addresses",
        "allocatable": "allocatable",
        "capacity": "capacity",
        "conditions": "conditions",
        "config": "config",
        "daemon_endpoints": "daemonEndpoints",
        "declared_features": "declaredFeatures",
        "features": "features",
        "images": "images",
        "node_info": "nodeInfo",
        "phase": "phase",
        "runtime_handlers": "runtimeHandlers",
        "volumes_attached": "volumesAttached",
        "volumes_in_use": "volumesInUse"
    }
    __properties: ClassVar[List[str]] = ["addresses", "allocatable", "capacity", "conditions", "config", "daemonEndpoints", "declaredFeatures", "features", "images", "nodeInfo", "phase", "runtimeHandlers", "volumesAttached", "volumesInUse"]

    @classmethod
    def __preprocess_input_names(
        cls,
        obj: Any,
        remove_hidden_storage_names: bool = True,
    ) -> Any:
        if not isinstance(obj, _Mapping):
            return obj
        obj = dict(obj)
        if "daemonEndpoints" not in obj and "daemon_endpoints" in obj:
            obj["daemonEndpoints"] = obj["daemon_endpoints"]
        obj.pop("daemon_endpoints", None)
        if "declaredFeatures" not in obj and "declared_features" in obj:
            obj["declaredFeatures"] = obj["declared_features"]
        obj.pop("declared_features", None)
        if "nodeInfo" not in obj and "node_info" in obj:
            obj["nodeInfo"] = obj["node_info"]
        obj.pop("node_info", None)
        if "runtimeHandlers" not in obj and "runtime_handlers" in obj:
            obj["runtimeHandlers"] = obj["runtime_handlers"]
        obj.pop("runtime_handlers", None)
        if "volumesAttached" not in obj and "volumes_attached" in obj:
            obj["volumesAttached"] = obj["volumes_attached"]
        obj.pop("volumes_attached", None)
        if "volumesInUse" not in obj and "volumes_in_use" in obj:
            obj["volumesInUse"] = obj["volumes_in_use"]
        obj.pop("volumes_in_use", None)
        return obj

    model_config = ConfigDict(
        validate_by_name=True,
        validate_by_alias=True,
        validate_assignment=True,
        extra="forbid",
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model"""
        return pprint.pformat(self.to_dict())

    def __repr__(self) -> str:
        """For print and pprint"""
        return self.to_str()

    def __eq__(self, other: object) -> bool:
        """Returns true if both objects are equal"""
        if not isinstance(other, V1NodeStatus):
            return False

        return self.to_dict() == other.to_dict()

    def __ne__(self, other: object) -> bool:
        """Returns true if both objects are not equal"""
        if not isinstance(other, V1NodeStatus):
            return True

        return not (self == other)


    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        to_openapi_dict = _get_openapi_to_dict(self)
        if to_openapi_dict is not None:
            return json.dumps(to_jsonable_python(to_openapi_dict(self)))
        return json.dumps(to_jsonable_python(self.to_dict()))

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

    def to_dict(self, serialize: bool = False) -> Dict[str, Any]:
        """Return all declared model fields using public or wire names."""
        return {
            ("addresses" if serialize else "addresses"): _to_legacy_value(getattr(self, "addresses", None), serialize),
            ("allocatable" if serialize else "allocatable"): _to_legacy_value(getattr(self, "allocatable", None), serialize),
            ("capacity" if serialize else "capacity"): _to_legacy_value(getattr(self, "capacity", None), serialize),
            ("conditions" if serialize else "conditions"): _to_legacy_value(getattr(self, "conditions", None), serialize),
            ("config" if serialize else "config"): _to_legacy_value(getattr(self, "config", None), serialize),
            ("daemonEndpoints" if serialize else "daemon_endpoints"): _to_legacy_value(getattr(self, "daemon_endpoints", None), serialize),
            ("declaredFeatures" if serialize else "declared_features"): _to_legacy_value(getattr(self, "declared_features", None), serialize),
            ("features" if serialize else "features"): _to_legacy_value(getattr(self, "features", None), serialize),
            ("images" if serialize else "images"): _to_legacy_value(getattr(self, "images", None), serialize),
            ("nodeInfo" if serialize else "node_info"): _to_legacy_value(getattr(self, "node_info", None), serialize),
            ("phase" if serialize else "phase"): _to_legacy_value(getattr(self, "phase", None), serialize),
            ("runtimeHandlers" if serialize else "runtime_handlers"): _to_legacy_value(getattr(self, "runtime_handlers", None), serialize),
            ("volumesAttached" if serialize else "volumes_attached"): _to_legacy_value(getattr(self, "volumes_attached", None), serialize),
            ("volumesInUse" if serialize else "volumes_in_use"): _to_legacy_value(getattr(self, "volumes_in_use", None), serialize),
        }

    def __openapi_generator_modern_projection(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 addresses (list)
        _items = []
        if self.addresses:
            for _item_addresses in self.addresses:
                _items.append(_to_openapi_value(_item_addresses) if _item_addresses is not None else None)
            _dict['addresses'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in conditions (list)
        _items = []
        if self.conditions:
            for _item_conditions in self.conditions:
                _items.append(_to_openapi_value(_item_conditions) if _item_conditions is not None else None)
            _dict['conditions'] = _items
        # override the default output from pydantic by calling `to_dict()` of config
        if self.config:
            _dict['config'] = _to_openapi_value(self.config)
        # override the default output from pydantic by calling `to_dict()` of daemon_endpoints
        if self.daemon_endpoints:
            _dict['daemonEndpoints'] = _to_openapi_value(self.daemon_endpoints)
        # override the default output from pydantic by calling `to_dict()` of features
        if self.features:
            _dict['features'] = _to_openapi_value(self.features)
        # override the default output from pydantic by calling `to_dict()` of each item in images (list)
        _items = []
        if self.images:
            for _item_images in self.images:
                _items.append(_to_openapi_value(_item_images) if _item_images is not None else None)
            _dict['images'] = _items
        # override the default output from pydantic by calling `to_dict()` of node_info
        if self.node_info:
            _dict['nodeInfo'] = _to_openapi_value(self.node_info)
        # override the default output from pydantic by calling `to_dict()` of each item in runtime_handlers (list)
        _items = []
        if self.runtime_handlers:
            for _item_runtime_handlers in self.runtime_handlers:
                _items.append(_to_openapi_value(_item_runtime_handlers) if _item_runtime_handlers is not None else None)
            _dict['runtimeHandlers'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in volumes_attached (list)
        _items = []
        if self.volumes_attached:
            for _item_volumes_attached in self.volumes_attached:
                _items.append(_to_openapi_value(_item_volumes_attached) if _item_volumes_attached is not None else None)
            _dict['volumesAttached'] = _items
        return _dict

    setattr(
        to_dict,
        _OPENAPI_GENERATOR_TO_DICT,
        __openapi_generator_modern_projection,
    )
    setattr(
        __openapi_generator_modern_projection,
        _OPENAPI_GENERATOR_TO_DICT,
        to_dict,
    )
    del __openapi_generator_modern_projection

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

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

        obj = _cast(
            Dict[str, Any],
            cls.__preprocess_input_names(
                obj,
                remove_hidden_storage_names=True,
            ),
        )

        _obj = cls.model_validate({
            "addresses": [V1NodeAddress.from_dict(_item) for _item in obj["addresses"]] if obj.get("addresses") is not None else None,
            "allocatable": obj.get("allocatable"),
            "capacity": obj.get("capacity"),
            "conditions": [V1NodeCondition.from_dict(_item) for _item in obj["conditions"]] if obj.get("conditions") is not None else None,
            "config": V1NodeConfigStatus.from_dict(obj["config"]) if obj.get("config") is not None else None,
            "daemonEndpoints": V1NodeDaemonEndpoints.from_dict(obj["daemonEndpoints"]) if obj.get("daemonEndpoints") is not None else None,
            "declaredFeatures": obj.get("declaredFeatures"),
            "features": V1NodeFeatures.from_dict(obj["features"]) if obj.get("features") is not None else None,
            "images": [V1ContainerImage.from_dict(_item) for _item in obj["images"]] if obj.get("images") is not None else None,
            "nodeInfo": V1NodeSystemInfo.from_dict(obj["nodeInfo"]) if obj.get("nodeInfo") is not None else None,
            "phase": obj.get("phase"),
            "runtimeHandlers": [V1NodeRuntimeHandler.from_dict(_item) for _item in obj["runtimeHandlers"]] if obj.get("runtimeHandlers") is not None else None,
            "volumesAttached": [V1AttachedVolume.from_dict(_item) for _item in obj["volumesAttached"]] if obj.get("volumesAttached") is not None else None,
            "volumesInUse": obj.get("volumesInUse")
        })
        return _obj
