# coding: utf-8

"""
    UniCourt Enterprise APIs

    <button><a href=\"/developers/enterpriseapi/api/download/UniCourt-Enterprise-API-Spec.yaml\" >Download UniCourt Enterprise APIs Specification</a></button> 

    The version of the OpenAPI document: 
    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, Field, StrictBool, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from unicourt.model.attorneys import Attorneys
from unicourt.model.case_cause_of_action import CaseCauseOfAction
from unicourt.model.case_charge import CaseCharge
from unicourt.model.case_documents import CaseDocuments
from unicourt.model.case_stats import CaseStats
from unicourt.model.case_status import CaseStatus
from unicourt.model.case_type import CaseType
from unicourt.model.court import Court
from unicourt.model.court_location import CourtLocation
from unicourt.model.docket_entries import DocketEntries
from unicourt.model.hearings import Hearings
from unicourt.model.judges import Judges
from unicourt.model.parties import Parties
from unicourt.model.related_cases import RelatedCases
from unicourt.model.source_case_data import SourceCaseData
from typing import Optional, Set
from typing_extensions import Self

class Case(BaseModel):
    """
    Case
    """ # noqa: E501
    object: Optional[Annotated[str, Field(min_length=4, strict=True, max_length=4)]] = Field(default='Case', description="Name of the object")
    case_id: Optional[Annotated[str, Field(min_length=18, strict=True, max_length=18)]] = Field(default=None, description="Unique identifier of Case.", alias="caseId")
    url: Optional[Annotated[str, Field(strict=True, max_length=500)]] = Field(default=None, description="URL to the case page in UniCourt Application.")
    case_number: Optional[Annotated[str, Field(min_length=3, strict=True, max_length=50)]] = Field(default=None, description="Case number as provided by Court.", alias="caseNumber")
    case_name: Optional[Annotated[str, Field(strict=True, max_length=250)]] = Field(default=None, description="Case name as provided by Court.", alias="caseName")
    filed_date: Optional[datetime] = Field(default=None, description="Filing date for the case provided by the Court. Formatted as YYYY-MM-DDTHH:MM:SS+ZZ:zz", alias="filedDate")
    has_only_meta_info: Optional[StrictBool] = Field(default=None, description="This field determines if this case object has only meta information. If the value is true and if the full information is required you would need to call the updateCase API.", alias="hasOnlyMetaInfo")
    court_service_status_id: Optional[Annotated[str, Field(min_length=18, strict=True, max_length=18)]] = Field(default=None, description="Court Service Status ID of the requested case where we can use it to get the service status", alias="courtServiceStatusId")
    court_service_status_api: Optional[Annotated[str, Field(strict=True, max_length=250)]] = Field(default=None, description="API to get the service statuses of the given case.", alias="courtServiceStatusAPI")
    court: Optional[Court] = None
    court_location: Optional[CourtLocation] = Field(default=None, alias="courtLocation")
    case_type: Optional[CaseType] = Field(default=None, alias="caseType")
    charge_array: Optional[List[CaseCharge]] = Field(default=None, description="Array of charges that are added to this case.", alias="chargeArray")
    case_status: Optional[CaseStatus] = Field(default=None, alias="caseStatus")
    cause_of_action_array: Optional[List[CaseCauseOfAction]] = Field(default=None, description="Array of cause of Actions that are added to this case.", alias="causeOfActionArray")
    first_fetch_date: Optional[datetime] = Field(default=None, description="The date and time when the case was first fetched from the Court. This date and time is in UTC. Formatted as YYYY-MM-DDTHH:MM:SS+ZZ:zz,.", alias="firstFetchDate")
    last_fetch_date: Optional[datetime] = Field(default=None, description="The date and time when the case was last fetched from the Court. This date and time is in UTC. Formatted as YYYY-MM-DDTHH:MM:SS+ZZ:zz, Note: It is not necessary that every time the case is fetched from Court we find changes in the case information. It could be that we already have the latest information from the Court and no changes exist.", alias="lastFetchDate")
    last_fetch_date_with_updates: Optional[datetime] = Field(default=None, description="The date and time when the case was last fetched from the Court where we found changes in the case information. This date and time is in UTC. Formatted as YYYY-MM-DDTHH:MM:SS+ZZ:zz,", alias="lastFetchDateWithUpdates")
    participants_last_fetch_date: Optional[datetime] = Field(default=None, description="The date and time when parties/attorneys were last updated from the Court. Formatted as YYYY-MM-DDTHH:MM:SS+ZZ:zz, Note: This is currently applicable for Federal PACER cases since we have an option to exclude parties and fetch only latest docket entries when updating cases to save PACER fees.", alias="participantsLastFetchDate")
    source_data_status: Optional[StrictStr] = Field(default=None, description="The status of source data of case. If the value of sourceDataStatus is SOURCE_DEPRECATED then it means that the Case has been migrated from old court site to a new court site and the data being shown in the API response is from a old court site. If the sourceDataStatus is NO_LONGER_AVAILABLE_IN_COURT then it means that a particular case is invalid in the court site.", alias="sourceDataStatus")
    source_case_data: Optional[SourceCaseData] = Field(default=None, alias="sourceCaseData")
    has_documents_with_preview: Optional[StrictBool] = Field(default=None, description="This field will be set to TRUE if atleast one document has a preview.", alias="hasDocumentsWithPreview")
    export_api: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="When a case is beyond the threshold of entities we provide this link so that the user can request and get all the data of the case with one additional call. This data will be zipped and sent via a webhoook.", alias="exportAPI")
    case_stats: Optional[CaseStats] = Field(default=None, alias="caseStats")
    parties: Optional[Parties] = None
    attorneys: Optional[Attorneys] = None
    judges: Optional[Judges] = None
    docket_entries: Optional[DocketEntries] = Field(default=None, alias="docketEntries")
    hearings: Optional[Hearings] = None
    case_documents: Optional[CaseDocuments] = Field(default=None, alias="caseDocuments")
    related_cases: Optional[RelatedCases] = Field(default=None, alias="relatedCases")
    __properties: ClassVar[List[str]] = ["object", "caseId", "url", "caseNumber", "caseName", "filedDate", "hasOnlyMetaInfo", "courtServiceStatusId", "courtServiceStatusAPI", "court", "courtLocation", "caseType", "chargeArray", "caseStatus", "causeOfActionArray", "firstFetchDate", "lastFetchDate", "lastFetchDateWithUpdates", "participantsLastFetchDate", "sourceDataStatus", "sourceCaseData", "hasDocumentsWithPreview", "exportAPI", "caseStats", "parties", "attorneys", "judges", "docketEntries", "hearings", "caseDocuments", "relatedCases"]

    @field_validator('source_data_status')
    def source_data_status_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['NO_LONGER_AVAILABLE_IN_COURT', 'null']):
            raise ValueError("must be one of enum values ('NO_LONGER_AVAILABLE_IN_COURT', 'null')")
        return value

    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 Case 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 court
        if self.court:
            _dict['court'] = self.court.to_dict()
        # override the default output from pydantic by calling `to_dict()` of court_location
        if self.court_location:
            _dict['courtLocation'] = self.court_location.to_dict()
        # override the default output from pydantic by calling `to_dict()` of case_type
        if self.case_type:
            _dict['caseType'] = self.case_type.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in charge_array (list)
        _items = []
        if self.charge_array:
            for _item in self.charge_array:
                if _item:
                    _items.append(_item.to_dict())
            _dict['chargeArray'] = _items
        # override the default output from pydantic by calling `to_dict()` of case_status
        if self.case_status:
            _dict['caseStatus'] = self.case_status.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in cause_of_action_array (list)
        _items = []
        if self.cause_of_action_array:
            for _item in self.cause_of_action_array:
                if _item:
                    _items.append(_item.to_dict())
            _dict['causeOfActionArray'] = _items
        # override the default output from pydantic by calling `to_dict()` of source_case_data
        if self.source_case_data:
            _dict['sourceCaseData'] = self.source_case_data.to_dict()
        # override the default output from pydantic by calling `to_dict()` of case_stats
        if self.case_stats:
            _dict['caseStats'] = self.case_stats.to_dict()
        # override the default output from pydantic by calling `to_dict()` of parties
        if self.parties:
            _dict['parties'] = self.parties.to_dict()
        # override the default output from pydantic by calling `to_dict()` of attorneys
        if self.attorneys:
            _dict['attorneys'] = self.attorneys.to_dict()
        # override the default output from pydantic by calling `to_dict()` of judges
        if self.judges:
            _dict['judges'] = self.judges.to_dict()
        # override the default output from pydantic by calling `to_dict()` of docket_entries
        if self.docket_entries:
            _dict['docketEntries'] = self.docket_entries.to_dict()
        # override the default output from pydantic by calling `to_dict()` of hearings
        if self.hearings:
            _dict['hearings'] = self.hearings.to_dict()
        # override the default output from pydantic by calling `to_dict()` of case_documents
        if self.case_documents:
            _dict['caseDocuments'] = self.case_documents.to_dict()
        # override the default output from pydantic by calling `to_dict()` of related_cases
        if self.related_cases:
            _dict['relatedCases'] = self.related_cases.to_dict()
        # set to None if url (nullable) is None
        # and model_fields_set contains the field
        if self.url is None and "url" in self.model_fields_set:
            _dict['url'] = None

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

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

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

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

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

        return _dict

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

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

        _obj = cls.model_validate({
            "object": obj.get("object") if obj.get("object") is not None else 'Case',
            "caseId": obj.get("caseId"),
            "url": obj.get("url"),
            "caseNumber": obj.get("caseNumber"),
            "caseName": obj.get("caseName"),
            "filedDate": obj.get("filedDate"),
            "hasOnlyMetaInfo": obj.get("hasOnlyMetaInfo"),
            "courtServiceStatusId": obj.get("courtServiceStatusId"),
            "courtServiceStatusAPI": obj.get("courtServiceStatusAPI"),
            "court": Court.from_dict(obj["court"]) if obj.get("court") is not None else None,
            "courtLocation": CourtLocation.from_dict(obj["courtLocation"]) if obj.get("courtLocation") is not None else None,
            "caseType": CaseType.from_dict(obj["caseType"]) if obj.get("caseType") is not None else None,
            "chargeArray": [CaseCharge.from_dict(_item) for _item in obj["chargeArray"]] if obj.get("chargeArray") is not None else None,
            "caseStatus": CaseStatus.from_dict(obj["caseStatus"]) if obj.get("caseStatus") is not None else None,
            "causeOfActionArray": [CaseCauseOfAction.from_dict(_item) for _item in obj["causeOfActionArray"]] if obj.get("causeOfActionArray") is not None else None,
            "firstFetchDate": obj.get("firstFetchDate"),
            "lastFetchDate": obj.get("lastFetchDate"),
            "lastFetchDateWithUpdates": obj.get("lastFetchDateWithUpdates"),
            "participantsLastFetchDate": obj.get("participantsLastFetchDate"),
            "sourceDataStatus": obj.get("sourceDataStatus"),
            "sourceCaseData": SourceCaseData.from_dict(obj["sourceCaseData"]) if obj.get("sourceCaseData") is not None else None,
            "hasDocumentsWithPreview": obj.get("hasDocumentsWithPreview"),
            "exportAPI": obj.get("exportAPI"),
            "caseStats": CaseStats.from_dict(obj["caseStats"]) if obj.get("caseStats") is not None else None,
            "parties": Parties.from_dict(obj["parties"]) if obj.get("parties") is not None else None,
            "attorneys": Attorneys.from_dict(obj["attorneys"]) if obj.get("attorneys") is not None else None,
            "judges": Judges.from_dict(obj["judges"]) if obj.get("judges") is not None else None,
            "docketEntries": DocketEntries.from_dict(obj["docketEntries"]) if obj.get("docketEntries") is not None else None,
            "hearings": Hearings.from_dict(obj["hearings"]) if obj.get("hearings") is not None else None,
            "caseDocuments": CaseDocuments.from_dict(obj["caseDocuments"]) if obj.get("caseDocuments") is not None else None,
            "relatedCases": RelatedCases.from_dict(obj["relatedCases"]) if obj.get("relatedCases") is not None else None
        })
        return _obj


