from typing import List, Union

from yattag import Doc

from ..exceptions import WQXException
from .FrequencyClassInformation import FrequencyClassInformation
from .MeasureCompact import MeasureCompact
from .SimpleContent import (BiologicalIndividualIdentifier,
                            BiologicalIntentName, GroupSummaryCount,
                            SampleTissueAnatomyName, SubjectTaxonomicName,
                            SubjectTaxonomicNameUserSupplied,
                            SubjectTaxonomicNameUserSuppliedReferenceText,
                            UnidentifiedSpeciesIdentifier)
from .TaxonomicDetails import TaxonomicDetails


class BiologicalResultDescription:
    """Allows for the reporting of biological result information."""

    __biologicalIntentName: BiologicalIntentName
    __biologicalIndividualIdentifier: BiologicalIndividualIdentifier
    __subjectTaxonomicName: SubjectTaxonomicName
    __subjectTaxonomicNameUserSupplied: SubjectTaxonomicNameUserSupplied
    __subjectTaxonomicNameUserSuppliedReferenceText: SubjectTaxonomicNameUserSuppliedReferenceText
    __unidentifiedSpeciesIdentifier: UnidentifiedSpeciesIdentifier
    __sampleTissueAnatomyName: SampleTissueAnatomyName
    __groupSummaryCount: GroupSummaryCount
    __groupSummaryWeightMeasure: MeasureCompact
    __taxonomicDetails: TaxonomicDetails
    __frequencyClassInformation: List[FrequencyClassInformation]

    def __init__(
        self,
        o:dict=None,
        *,
        biologicalIntentName: BiologicalIntentName = None,
        biologicalIndividualIdentifier: BiologicalIndividualIdentifier = None,
        subjectTaxonomicName: SubjectTaxonomicName = None,
        subjectTaxonomicNameUserSupplied: SubjectTaxonomicNameUserSupplied = None,
        subjectTaxonomicNameUserSuppliedReferenceText: SubjectTaxonomicNameUserSuppliedReferenceText = None,
        unidentifiedSpeciesIdentifier: UnidentifiedSpeciesIdentifier = None,
        sampleTissueAnatomyName: SampleTissueAnatomyName = None,
        groupSummaryCount: GroupSummaryCount = None,
        groupSummaryWeightMeasure: MeasureCompact = None,
        taxonomicDetails: TaxonomicDetails = None,
        frequencyClassInformation: FrequencyClassInformation = None
    ):
        if isinstance(o, BiologicalResultDescription):
            # Assign attributes from object without typechecking
            self.__biologicalIntentName = o.biologicalIntentName
            self.__biologicalIndividualIdentifier = o.biologicalIndividualIdentifier
            self.__subjectTaxonomicName = o.subjectTaxonomicName
            self.__subjectTaxonomicNameUserSupplied = o.subjectTaxonomicNameUserSupplied
            self.__subjectTaxonomicNameUserSuppliedReferenceText = (
                o.subjectTaxonomicNameUserSuppliedReferenceText
            )
            self.__unidentifiedSpeciesIdentifier = o.unidentifiedSpeciesIdentifier
            self.__sampleTissueAnatomyName = o.sampleTissueAnatomyName
            self.__groupSummaryCount = o.groupSummaryCount
            self.__groupSummaryWeightMeasure = o.groupSummaryWeightMeasure
            self.__taxonomicDetails = o.taxonomicDetails
            self.__frequencyClassInformation = o.frequencyClassInformation
        elif isinstance(o, dict):
            # Assign attributes from dictionary with typechecking
            self.biologicalIntentName = o.get("biologicalIntentName")
            self.biologicalIndividualIdentifier = o.get(
                "biologicalIndividualIdentifier"
            )
            self.subjectTaxonomicName = o.get("subjectTaxonomicName")
            self.subjectTaxonomicNameUserSupplied = o.get(
                "subjectTaxonomicNameUserSupplied"
            )
            self.subjectTaxonomicNameUserSuppliedReferenceText = o.get(
                "subjectTaxonomicNameUserSuppliedReferenceText"
            )
            self.unidentifiedSpeciesIdentifier = o.get("unidentifiedSpeciesIdentifier")
            self.sampleTissueAnatomyName = o.get("sampleTissueAnatomyName")
            self.groupSummaryCount = o.get("groupSummaryCount")
            self.groupSummaryWeightMeasure = o.get("groupSummaryWeightMeasure")
            self.taxonomicDetails = o.get("taxonomicDetails")
            self.frequencyClassInformation = o.get("frequencyClassInformation")
        else:
            # Assign attributes from named keywords with typechecking
            self.biologicalIntentName = biologicalIntentName
            self.biologicalIndividualIdentifier = biologicalIndividualIdentifier
            self.subjectTaxonomicName = subjectTaxonomicName
            self.subjectTaxonomicNameUserSupplied = subjectTaxonomicNameUserSupplied
            self.subjectTaxonomicNameUserSuppliedReferenceText = (
                subjectTaxonomicNameUserSuppliedReferenceText
            )
            self.unidentifiedSpeciesIdentifier = unidentifiedSpeciesIdentifier
            self.sampleTissueAnatomyName = sampleTissueAnatomyName
            self.groupSummaryCount = groupSummaryCount
            self.groupSummaryWeightMeasure = groupSummaryWeightMeasure
            self.taxonomicDetails = taxonomicDetails
            self.frequencyClassInformation = frequencyClassInformation

    @property
    def biologicalIntentName(self) -> BiologicalIntentName:
        return self.__biologicalIntentName

    @biologicalIntentName.setter
    def biologicalIntentName(self, val: BiologicalIntentName) -> None:
        self.__biologicalIntentName = None if val is None else BiologicalIntentName(val)

    @property
    def biologicalIndividualIdentifier(self) -> BiologicalIndividualIdentifier:
        return self.__biologicalIndividualIdentifier

    @biologicalIndividualIdentifier.setter
    def biologicalIndividualIdentifier(
        self, val: BiologicalIndividualIdentifier
    ) -> None:
        self.__biologicalIndividualIdentifier = (
            None if val is None else BiologicalIndividualIdentifier(val)
        )

    @property
    def subjectTaxonomicName(self) -> SubjectTaxonomicName:
        return self.__subjectTaxonomicName

    @subjectTaxonomicName.setter
    def subjectTaxonomicName(self, val: SubjectTaxonomicName) -> None:
        self.__subjectTaxonomicName = None if val is None else SubjectTaxonomicName(val)

    @property
    def subjectTaxonomicNameUserSupplied(self) -> SubjectTaxonomicNameUserSupplied:
        return self.__subjectTaxonomicNameUserSupplied

    @subjectTaxonomicNameUserSupplied.setter
    def subjectTaxonomicNameUserSupplied(
        self, val: SubjectTaxonomicNameUserSupplied
    ) -> None:
        self.__subjectTaxonomicNameUserSupplied = (
            None if val is None else SubjectTaxonomicNameUserSupplied(val)
        )

    @property
    def subjectTaxonomicNameUserSuppliedReferenceText(
        self,
    ) -> SubjectTaxonomicNameUserSuppliedReferenceText:
        return self.__subjectTaxonomicNameUserSuppliedReferenceText

    @subjectTaxonomicNameUserSuppliedReferenceText.setter
    def subjectTaxonomicNameUserSuppliedReferenceText(
        self, val: SubjectTaxonomicNameUserSuppliedReferenceText
    ) -> None:
        self.__subjectTaxonomicNameUserSuppliedReferenceText = (
            None if val is None else SubjectTaxonomicNameUserSuppliedReferenceText(val)
        )

    @property
    def unidentifiedSpeciesIdentifier(self) -> UnidentifiedSpeciesIdentifier:
        return self.__unidentifiedSpeciesIdentifier

    @unidentifiedSpeciesIdentifier.setter
    def unidentifiedSpeciesIdentifier(self, val: UnidentifiedSpeciesIdentifier) -> None:
        self.__unidentifiedSpeciesIdentifier = (
            None if val is None else UnidentifiedSpeciesIdentifier(val)
        )

    @property
    def sampleTissueAnatomyName(self) -> SampleTissueAnatomyName:
        return self.__sampleTissueAnatomyName

    @sampleTissueAnatomyName.setter
    def sampleTissueAnatomyName(self, val: SampleTissueAnatomyName) -> None:
        self.__sampleTissueAnatomyName = (
            None if val is None else SampleTissueAnatomyName(val)
        )

    @property
    def groupSummaryCount(self) -> GroupSummaryCount:
        """Captures the total count or total sample weight for a Group Summary."""
        return self.__groupSummaryCount

    @groupSummaryCount.setter
    def groupSummaryCount(self, val: GroupSummaryCount) -> None:
        """Captures the total count or total sample weight for a Group Summary."""
        self.__groupSummaryCount = None if val is None else GroupSummaryCount(val)

    @property
    def groupSummaryWeightMeasure(self) -> MeasureCompact:
        return self.__groupSummaryWeightMeasure

    @groupSummaryWeightMeasure.setter
    def groupSummaryWeightMeasure(self, val: MeasureCompact) -> None:
        self.__groupSummaryWeightMeasure = None if val is None else MeasureCompact(val)

    @property
    def taxonomicDetails(self) -> TaxonomicDetails:
        return self.__taxonomicDetails

    @taxonomicDetails.setter
    def taxonomicDetails(self, val: TaxonomicDetails) -> None:
        self.__taxonomicDetails = None if val is None else TaxonomicDetails(val)

    @property
    def frequencyClassInformation(self) -> FrequencyClassInformation:
        return self.__frequencyClassInformation

    @frequencyClassInformation.setter
    def frequencyClassInformation(
        self, val: Union[FrequencyClassInformation, List[FrequencyClassInformation]]
    ) -> None:
        if val is None:
            self.__frequencyClassInformation = []
        elif isinstance(val, list):
            r: List[FrequencyClassInformation] = []
            for x in val:
                r.append(FrequencyClassInformation(x))
            self.__frequencyClassInformation = r
        else:
            self.__frequencyClassInformation = [FrequencyClassInformation(val)]

    def generateXML(self, name: str = "BiologicalResultDescription") -> str:
        doc = Doc()
        asis = doc.asis
        line = doc.line
        tag = doc.tag

        with tag(name):
            if self.__biologicalIntentName is None:
                raise WQXException("Attribute 'biologicalIntentName' is required.")
            line("BiologicalIntentName", self.__biologicalIntentName)
            if self.__biologicalIndividualIdentifier is not None:
                line(
                    "BiologicalIndividualIdentifier",
                    self.__biologicalIndividualIdentifier,
                )
            if self.__subjectTaxonomicName is None:
                raise WQXException("Attribute 'subjectTaxonomicName' is required.")
            line("SubjectTaxonomicName", self.__subjectTaxonomicName)
            if self.__subjectTaxonomicNameUserSupplied is not None:
                line(
                    "SubjectTaxonomicNameUserSupplied",
                    self.__subjectTaxonomicNameUserSupplied,
                )
            if self.__subjectTaxonomicNameUserSuppliedReferenceText is not None:
                line(
                    "SubjectTaxonomicNameUserSuppliedReferenceText",
                    self.__subjectTaxonomicNameUserSuppliedReferenceText,
                )
            if self.__unidentifiedSpeciesIdentifier is not None:
                line(
                    "UnidentifiedSpeciesIdentifier",
                    self.__unidentifiedSpeciesIdentifier,
                )
            if self.__sampleTissueAnatomyName is not None:
                line("SampleTissueAnatomyName", self.__sampleTissueAnatomyName)
            if self.__groupSummaryCount is not None:
                line("GroupSummaryCount", self.__groupSummaryCount)
            if self.__groupSummaryWeightMeasure is not None:
                asis(
                    self.__groupSummaryWeightMeasure.generateXML(
                        "GroupSummaryWeightMeasure"
                    )
                )
            if self.__taxonomicDetails is not None:
                asis(self.__taxonomicDetails.generateXML("TaxonomicDetails"))
            if len(self.__frequencyClassInformation) > 3:
                raise WQXException(
                    "Attribute frequencyClassInformation must be a list of 0 to 3 FrequencyClassInformation objects."
                )
            for x in self.__frequencyClassInformation:
                asis(x.generateXML("FrequencyClassInformation"))

        return doc.getvalue()
