# 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 json
import pprint
from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator
from typing import Any, List, Optional
from airflow_client.client.models.new_task_response import NewTaskResponse
from airflow_client.client.models.task_instance_response import TaskInstanceResponse
from pydantic import StrictStr, Field
from typing import Union, List, Set, Optional, Dict
from typing_extensions import Literal, Self

TASKINSTANCESINNER_ONE_OF_SCHEMAS = ["NewTaskResponse", "TaskInstanceResponse"]

class TaskInstancesInner(BaseModel):
    """
    TaskInstancesInner
    """
    # data type: TaskInstanceResponse
    oneof_schema_1_validator: Optional[TaskInstanceResponse] = None
    # data type: NewTaskResponse
    oneof_schema_2_validator: Optional[NewTaskResponse] = None
    actual_instance: Optional[Union[NewTaskResponse, TaskInstanceResponse]] = None
    one_of_schemas: Set[str] = { "NewTaskResponse", "TaskInstanceResponse" }

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


    def __init__(self, *args, **kwargs) -> None:
        if args:
            if len(args) > 1:
                raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
            if kwargs:
                raise ValueError("If a position argument is used, keyword arguments cannot be used.")
            super().__init__(actual_instance=args[0])
        else:
            super().__init__(**kwargs)

    @field_validator('actual_instance')
    def actual_instance_must_validate_oneof(cls, v):
        instance = TaskInstancesInner.model_construct()
        error_messages = []
        match = 0
        # validate data type: TaskInstanceResponse
        if not isinstance(v, TaskInstanceResponse):
            error_messages.append(f"Error! Input type `{type(v)}` is not `TaskInstanceResponse`")
        else:
            match += 1
        # validate data type: NewTaskResponse
        if not isinstance(v, NewTaskResponse):
            error_messages.append(f"Error! Input type `{type(v)}` is not `NewTaskResponse`")
        else:
            match += 1
        if match > 1:
            # more than 1 match
            raise ValueError("Multiple matches found when setting `actual_instance` in TaskInstancesInner with oneOf schemas: NewTaskResponse, TaskInstanceResponse. Details: " + ", ".join(error_messages))
        elif match == 0:
            # no match
            raise ValueError("No match found when setting `actual_instance` in TaskInstancesInner with oneOf schemas: NewTaskResponse, TaskInstanceResponse. Details: " + ", ".join(error_messages))
        else:
            return v

    @classmethod
    def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
        return cls.from_json(json.dumps(obj))

    @classmethod
    def from_json(cls, json_str: str) -> Self:
        """Returns the object represented by the json string"""
        instance = cls.model_construct()
        error_messages = []
        match = 0

        # deserialize data into TaskInstanceResponse
        try:
            instance.actual_instance = TaskInstanceResponse.from_json(json_str)
            match += 1
        except (ValidationError, ValueError) as e:
            error_messages.append(str(e))
        # deserialize data into NewTaskResponse
        try:
            instance.actual_instance = NewTaskResponse.from_json(json_str)
            match += 1
        except (ValidationError, ValueError) as e:
            error_messages.append(str(e))

        if match > 1:
            # more than 1 match
            raise ValueError("Multiple matches found when deserializing the JSON string into TaskInstancesInner with oneOf schemas: NewTaskResponse, TaskInstanceResponse. Details: " + ", ".join(error_messages))
        elif match == 0:
            # no match
            raise ValueError("No match found when deserializing the JSON string into TaskInstancesInner with oneOf schemas: NewTaskResponse, TaskInstanceResponse. Details: " + ", ".join(error_messages))
        else:
            return instance

    def to_json(self) -> str:
        """Returns the JSON representation of the actual instance"""
        if self.actual_instance is None:
            return "null"

        if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json):
            return self.actual_instance.to_json()
        else:
            return json.dumps(self.actual_instance)

    def to_dict(self) -> Optional[Union[Dict[str, Any], NewTaskResponse, TaskInstanceResponse]]:
        """Returns the dict representation of the actual instance"""
        if self.actual_instance is None:
            return None

        if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict):
            return self.actual_instance.to_dict()
        else:
            # primitive type
            return self.actual_instance

    def to_str(self) -> str:
        """Returns the string representation of the actual instance"""
        return pprint.pformat(self.model_dump())


