# coding: utf-8

"""
    ACROSS Server

    Server providing tools and utilities for various NASA missions to aid in coordination of large observation efforts.

    The version of the OpenAPI document: 1.1.0
    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, StrictFloat, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, Union
from across.sdk.v1.models.bandpass import Bandpass
from across.sdk.v1.models.coordinate import Coordinate
from across.sdk.v1.models.date_range import DateRange
from across.sdk.v1.models.ivoa_obs_category import IVOAObsCategory
from across.sdk.v1.models.ivoa_obs_tracking_type import IVOAObsTrackingType
from across.sdk.v1.models.observation_status import ObservationStatus
from across.sdk.v1.models.observation_type import ObservationType
from across.sdk.v1.models.unit_value import UnitValue
from typing import Optional, Set
from typing_extensions import Self

class ObservationCreate(BaseModel):
    """
    ObservationCreate
    """ # noqa: E501
    instrument_id: StrictStr
    object_name: StrictStr
    pointing_position: Optional[Coordinate] = None
    date_range: DateRange
    external_observation_id: StrictStr
    type: ObservationType
    status: ObservationStatus
    pointing_angle: Optional[Union[StrictFloat, StrictInt]] = None
    exposure_time: Optional[Union[StrictFloat, StrictInt]] = None
    reason: Optional[StrictStr] = None
    description: Optional[StrictStr] = None
    proposal_reference: Optional[StrictStr] = None
    object_position: Optional[Coordinate] = None
    depth: Optional[UnitValue] = None
    bandpass: Bandpass
    t_resolution: Optional[Union[StrictFloat, StrictInt]] = None
    em_res_power: Optional[Union[StrictFloat, StrictInt]] = None
    o_ucd: Optional[StrictStr] = None
    pol_states: Optional[StrictStr] = None
    pol_xel: Optional[StrictStr] = None
    category: Optional[IVOAObsCategory] = None
    priority: Optional[StrictInt] = None
    tracking_type: Optional[IVOAObsTrackingType] = None
    created_on: Optional[datetime] = None
    created_by_id: Optional[StrictStr] = None
    __properties: ClassVar[List[str]] = ["instrument_id", "object_name", "pointing_position", "date_range", "external_observation_id", "type", "status", "pointing_angle", "exposure_time", "reason", "description", "proposal_reference", "object_position", "depth", "bandpass", "t_resolution", "em_res_power", "o_ucd", "pol_states", "pol_xel", "category", "priority", "tracking_type", "created_on", "created_by_id"]

    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 ObservationCreate 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 pointing_position
        if self.pointing_position:
            _dict['pointing_position'] = self.pointing_position.to_dict()
        # override the default output from pydantic by calling `to_dict()` of date_range
        if self.date_range:
            _dict['date_range'] = self.date_range.to_dict()
        # override the default output from pydantic by calling `to_dict()` of object_position
        if self.object_position:
            _dict['object_position'] = self.object_position.to_dict()
        # override the default output from pydantic by calling `to_dict()` of depth
        if self.depth:
            _dict['depth'] = self.depth.to_dict()
        # override the default output from pydantic by calling `to_dict()` of bandpass
        if self.bandpass:
            _dict['bandpass'] = self.bandpass.to_dict()
        # set to None if pointing_position (nullable) is None
        # and model_fields_set contains the field
        if self.pointing_position is None and "pointing_position" in self.model_fields_set:
            _dict['pointing_position'] = None

        # set to None if pointing_angle (nullable) is None
        # and model_fields_set contains the field
        if self.pointing_angle is None and "pointing_angle" in self.model_fields_set:
            _dict['pointing_angle'] = None

        # set to None if exposure_time (nullable) is None
        # and model_fields_set contains the field
        if self.exposure_time is None and "exposure_time" in self.model_fields_set:
            _dict['exposure_time'] = None

        # set to None if reason (nullable) is None
        # and model_fields_set contains the field
        if self.reason is None and "reason" in self.model_fields_set:
            _dict['reason'] = None

        # set to None if description (nullable) is None
        # and model_fields_set contains the field
        if self.description is None and "description" in self.model_fields_set:
            _dict['description'] = None

        # set to None if proposal_reference (nullable) is None
        # and model_fields_set contains the field
        if self.proposal_reference is None and "proposal_reference" in self.model_fields_set:
            _dict['proposal_reference'] = None

        # set to None if object_position (nullable) is None
        # and model_fields_set contains the field
        if self.object_position is None and "object_position" in self.model_fields_set:
            _dict['object_position'] = None

        # set to None if depth (nullable) is None
        # and model_fields_set contains the field
        if self.depth is None and "depth" in self.model_fields_set:
            _dict['depth'] = None

        # set to None if t_resolution (nullable) is None
        # and model_fields_set contains the field
        if self.t_resolution is None and "t_resolution" in self.model_fields_set:
            _dict['t_resolution'] = None

        # set to None if em_res_power (nullable) is None
        # and model_fields_set contains the field
        if self.em_res_power is None and "em_res_power" in self.model_fields_set:
            _dict['em_res_power'] = None

        # set to None if o_ucd (nullable) is None
        # and model_fields_set contains the field
        if self.o_ucd is None and "o_ucd" in self.model_fields_set:
            _dict['o_ucd'] = None

        # set to None if pol_states (nullable) is None
        # and model_fields_set contains the field
        if self.pol_states is None and "pol_states" in self.model_fields_set:
            _dict['pol_states'] = None

        # set to None if pol_xel (nullable) is None
        # and model_fields_set contains the field
        if self.pol_xel is None and "pol_xel" in self.model_fields_set:
            _dict['pol_xel'] = None

        # set to None if category (nullable) is None
        # and model_fields_set contains the field
        if self.category is None and "category" in self.model_fields_set:
            _dict['category'] = None

        # set to None if priority (nullable) is None
        # and model_fields_set contains the field
        if self.priority is None and "priority" in self.model_fields_set:
            _dict['priority'] = None

        # set to None if tracking_type (nullable) is None
        # and model_fields_set contains the field
        if self.tracking_type is None and "tracking_type" in self.model_fields_set:
            _dict['tracking_type'] = None

        # set to None if created_on (nullable) is None
        # and model_fields_set contains the field
        if self.created_on is None and "created_on" in self.model_fields_set:
            _dict['created_on'] = None

        # set to None if created_by_id (nullable) is None
        # and model_fields_set contains the field
        if self.created_by_id is None and "created_by_id" in self.model_fields_set:
            _dict['created_by_id'] = None

        return _dict

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

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

        _obj = cls.model_validate({
            "instrument_id": obj.get("instrument_id"),
            "object_name": obj.get("object_name"),
            "pointing_position": Coordinate.from_dict(obj["pointing_position"]) if obj.get("pointing_position") is not None else None,
            "date_range": DateRange.from_dict(obj["date_range"]) if obj.get("date_range") is not None else None,
            "external_observation_id": obj.get("external_observation_id"),
            "type": obj.get("type"),
            "status": obj.get("status"),
            "pointing_angle": obj.get("pointing_angle"),
            "exposure_time": obj.get("exposure_time"),
            "reason": obj.get("reason"),
            "description": obj.get("description"),
            "proposal_reference": obj.get("proposal_reference"),
            "object_position": Coordinate.from_dict(obj["object_position"]) if obj.get("object_position") is not None else None,
            "depth": UnitValue.from_dict(obj["depth"]) if obj.get("depth") is not None else None,
            "bandpass": Bandpass.from_dict(obj["bandpass"]) if obj.get("bandpass") is not None else None,
            "t_resolution": obj.get("t_resolution"),
            "em_res_power": obj.get("em_res_power"),
            "o_ucd": obj.get("o_ucd"),
            "pol_states": obj.get("pol_states"),
            "pol_xel": obj.get("pol_xel"),
            "category": obj.get("category"),
            "priority": obj.get("priority"),
            "tracking_type": obj.get("tracking_type"),
            "created_on": obj.get("created_on"),
            "created_by_id": obj.get("created_by_id")
        })
        return _obj


