# WARNING: This file is autogenerated by FHIR Schema Codegen.
# https://github.com/fhir-schema/fhir-schema-codegen
# Any manual changes made to this file may be overwritten.

from __future__ import annotations
from pydantic import ConfigDict, Field
from typing import List as PyList

from fhirschemapy.R4B.base import BackboneElement, CodeableConcept, Identifier
from fhirschemapy.R4B.domain_resource import DomainResource


class SubstanceSourceMaterialFractionDescription(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    fraction: str | None = Field(None, alias="fraction", serialization_alias="fraction")
    material_type: CodeableConcept | None = Field(
        None, alias="materialType", serialization_alias="materialType"
    )


class SubstanceSourceMaterialOrganism(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    author: PyList[SubstanceSourceMaterialOrganismAuthor] | None = Field(
        None, alias="author", serialization_alias="author"
    )
    family: CodeableConcept | None = Field(
        None, alias="family", serialization_alias="family"
    )
    genus: CodeableConcept | None = Field(
        None, alias="genus", serialization_alias="genus"
    )
    hybrid: SubstanceSourceMaterialOrganismHybrid | None = Field(
        None, alias="hybrid", serialization_alias="hybrid"
    )
    intraspecific_description: str | None = Field(
        None,
        alias="intraspecificDescription",
        serialization_alias="intraspecificDescription",
    )
    intraspecific_type: CodeableConcept | None = Field(
        None, alias="intraspecificType", serialization_alias="intraspecificType"
    )
    organism_general: SubstanceSourceMaterialOrganismOrganismGeneral | None = Field(
        None, alias="organismGeneral", serialization_alias="organismGeneral"
    )
    species: CodeableConcept | None = Field(
        None, alias="species", serialization_alias="species"
    )


class SubstanceSourceMaterialOrganismAuthor(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    author_description: str | None = Field(
        None, alias="authorDescription", serialization_alias="authorDescription"
    )
    author_type: CodeableConcept | None = Field(
        None, alias="authorType", serialization_alias="authorType"
    )


class SubstanceSourceMaterialOrganismHybrid(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    hybrid_type: CodeableConcept | None = Field(
        None, alias="hybridType", serialization_alias="hybridType"
    )
    maternal_organism_id: str | None = Field(
        None, alias="maternalOrganismId", serialization_alias="maternalOrganismId"
    )
    maternal_organism_name: str | None = Field(
        None, alias="maternalOrganismName", serialization_alias="maternalOrganismName"
    )
    paternal_organism_id: str | None = Field(
        None, alias="paternalOrganismId", serialization_alias="paternalOrganismId"
    )
    paternal_organism_name: str | None = Field(
        None, alias="paternalOrganismName", serialization_alias="paternalOrganismName"
    )


class SubstanceSourceMaterialOrganismOrganismGeneral(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    class_: CodeableConcept | None = Field(
        None, alias="class", serialization_alias="class"
    )
    kingdom: CodeableConcept | None = Field(
        None, alias="kingdom", serialization_alias="kingdom"
    )
    order: CodeableConcept | None = Field(
        None, alias="order", serialization_alias="order"
    )
    phylum: CodeableConcept | None = Field(
        None, alias="phylum", serialization_alias="phylum"
    )


class SubstanceSourceMaterialPartDescription(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    part: CodeableConcept | None = Field(None, alias="part", serialization_alias="part")
    part_location: CodeableConcept | None = Field(
        None, alias="partLocation", serialization_alias="partLocation"
    )


class SubstanceSourceMaterial(DomainResource):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    resource_type: str = Field(
        default="SubstanceSourceMaterial",
        alias="resourceType",
        serialization_alias="resourceType",
        frozen=True,
        pattern="SubstanceSourceMaterial",
    )

    country_of_origin: PyList[CodeableConcept] | None = Field(
        None, alias="countryOfOrigin", serialization_alias="countryOfOrigin"
    )
    development_stage: CodeableConcept | None = Field(
        None, alias="developmentStage", serialization_alias="developmentStage"
    )
    fraction_description: PyList[SubstanceSourceMaterialFractionDescription] | None = (
        Field(
            None, alias="fractionDescription", serialization_alias="fractionDescription"
        )
    )
    geographical_location: PyList[str] | None = Field(
        None, alias="geographicalLocation", serialization_alias="geographicalLocation"
    )
    organism: SubstanceSourceMaterialOrganism | None = Field(
        None, alias="organism", serialization_alias="organism"
    )
    organism_id: Identifier | None = Field(
        None, alias="organismId", serialization_alias="organismId"
    )
    organism_name: str | None = Field(
        None, alias="organismName", serialization_alias="organismName"
    )
    parent_substance_id: PyList[Identifier] | None = Field(
        None, alias="parentSubstanceId", serialization_alias="parentSubstanceId"
    )
    parent_substance_name: PyList[str] | None = Field(
        None, alias="parentSubstanceName", serialization_alias="parentSubstanceName"
    )
    part_description: PyList[SubstanceSourceMaterialPartDescription] | None = Field(
        None, alias="partDescription", serialization_alias="partDescription"
    )
    source_material_class: CodeableConcept | None = Field(
        None, alias="sourceMaterialClass", serialization_alias="sourceMaterialClass"
    )
    source_material_state: CodeableConcept | None = Field(
        None, alias="sourceMaterialState", serialization_alias="sourceMaterialState"
    )
    source_material_type: CodeableConcept | None = Field(
        None, alias="sourceMaterialType", serialization_alias="sourceMaterialType"
    )

    def to_json(self, indent: int | None = None) -> str:
        return self.model_dump_json(
            exclude_unset=True, exclude_none=True, indent=indent
        )

    @classmethod
    def from_json(cls, json: str) -> SubstanceSourceMaterial:
        return cls.model_validate_json(json)
