from ..exceptions import WQXException
from .BibliographicReference import BibliographicReference
from .SimpleContent import (
  CellFormName,
  CellShapeName,
  FunctionalFeedingGroupName,
  HabitName,
  TaxonomicPollutionTolerance,
  TaxonomicPollutionToleranceScaleText,
  TrophicLevelName,
  VoltinismName
)
from typing import List, Union
from yattag import Doc

class TaxonomicDetails:
  """This section allows for the further definition of user-defined details for taxa."""

  __cellFormName: CellFormName
  __cellShapeName: CellShapeName
  __habitName: HabitName
  __voltinismName: VoltinismName
  __taxonomicPollutionTolerance: TaxonomicPollutionTolerance
  __taxonomicPollutionToleranceScaleText: TaxonomicPollutionToleranceScaleText
  __trophicLevelName: TrophicLevelName
  __functionalFeedingGroupName: FunctionalFeedingGroupName
  __taxonomicDetailsCitation: BibliographicReference

  def __init__(self, o=None, *,
    cellFormName:CellFormName = None,
    cellShapeName:CellShapeName = None,
    habitName:HabitName = None,
    voltinismName:VoltinismName = None,
    taxonomicPollutionTolerance:TaxonomicPollutionTolerance = None,
    taxonomicPollutionToleranceScaleText:TaxonomicPollutionToleranceScaleText = None,
    trophicLevelName:TrophicLevelName = None,
    functionalFeedingGroupName:FunctionalFeedingGroupName = None,
    taxonomicDetailsCitation:BibliographicReference = None
  ):
    if isinstance(o, TaxonomicDetails):
      # Assign attributes from objects without typechecking
      self.__cellFormName = o.cellFormName
      self.__cellShapeName = o.cellShapeName
      self.__habitName = o.habitName
      self.__voltinismName = o.voltinismName
      self.__taxonomicPollutionTolerance = o.taxonomicPollutionTolerance
      self.__taxonomicPollutionToleranceScaleText = o.taxonomicPollutionToleranceScaleText
      self.__trophicLevelName = o.trophicLevelName
      self.__functionalFeedingGroupName = o.functionalFeedingGroupName
      self.__taxonomicDetailsCitation = o.taxonomicDetailsCitation
    elif isinstance(o, dict):
      # Assign attributes from dictionary with typechecking
      self.cellFormName = o.get('cellFormName', default = None)
      self.cellShapeName = o.get('cellShapeName', default = None)
      self.habitName = o.get('habitName', default = None)
      self.voltinismName = o.get('voltinismName', default = None)
      self.taxonomicPollutionTolerance = o.get('taxonomicPollutionTolerance', default = None)
      self.taxonomicPollutionToleranceScaleText = o.get('taxonomicPollutionToleranceScaleText', default = None)
      self.trophicLevelName = o.get('trophicLevelName', default = None)
      self.functionalFeedingGroupName = o.get('functionalFeedingGroupName', default = None)
      self.taxonomicDetailsCitation = o.get('taxonomicDetailsCitation', default = None)
    else:
      # Assign attributes from named keywords with typechecking
      self.cellFormName = cellFormName
      self.cellShapeName = cellShapeName
      self.habitName = habitName
      self.voltinismName = voltinismName
      self.taxonomicPollutionTolerance = taxonomicPollutionTolerance
      self.taxonomicPollutionToleranceScaleText = taxonomicPollutionToleranceScaleText
      self.trophicLevelName = trophicLevelName
      self.functionalFeedingGroupName = functionalFeedingGroupName
      self.taxonomicDetailsCitation = taxonomicDetailsCitation

  @property
  def cellFormName(self) -> CellFormName:
    return self.__cellFormName
  @cellFormName.setter
  def cellFormName(self, val:CellFormName) -> None:
    self.__cellFormName = None if val is None else CellFormName(val)

  @property
  def cellShapeName(self) -> CellShapeName:
    return self.__cellShapeName
  @cellShapeName.setter
  def cellShapeName(self, val:CellShapeName) -> None:
    self.__cellShapeName = None if val is None else CellShapeName(val)

  @property
  def habitName(self) -> HabitName:
    return self.__habitName
  @habitName.setter
  def habitName(self, val:Union[HabitName,List[HabitName]]) -> None:
    if val is None:
      self.__habitName = []
    elif isinstance(val, list):
      r:List[HabitName] = []
      for x in val:
        r.append(HabitName(x))
      self.__habitName = r
    else:
      self.__habitName = [HabitName(val)]

  @property
  def voltinismName(self) -> VoltinismName:
    return self.__voltinismName
  @voltinismName.setter
  def voltinismName(self, val:VoltinismName) -> None:
    self.__voltinismName = None if val is None else VoltinismName(val)

  @property
  def taxonomicPollutionTolerance(self) -> TaxonomicPollutionTolerance:
    return self.__taxonomicPollutionTolerance
  @taxonomicPollutionTolerance.setter
  def taxonomicPollutionTolerance(self, val:TaxonomicPollutionTolerance) -> None:
    self.__taxonomicPollutionTolerance = None if val is None else TaxonomicPollutionTolerance(val)

  @property
  def taxonomicPollutionToleranceScaleText(self) -> TaxonomicPollutionToleranceScaleText:
    return self.__taxonomicPollutionToleranceScaleText
  @taxonomicPollutionToleranceScaleText.setter
  def taxonomicPollutionToleranceScaleText(self, val:TaxonomicPollutionToleranceScaleText) -> None:
    self.__taxonomicPollutionToleranceScaleText = None if val is None else TaxonomicPollutionToleranceScaleText(val)

  @property
  def trophicLevelName(self) -> TrophicLevelName:
    return self.__trophicLevelName
  @trophicLevelName.setter
  def trophicLevelName(self, val:TrophicLevelName) -> None:
    self.__trophicLevelName = None if val is None else TrophicLevelName(val)

  @property
  def functionalFeedingGroupName(self) -> FunctionalFeedingGroupName:
    return self.__functionalFeedingGroupName
  @functionalFeedingGroupName.setter
  def functionalFeedingGroupName(self, val:Union[FunctionalFeedingGroupName,List[FunctionalFeedingGroupName]]) -> None:
    if val is None:
      self.__functionalFeedingGroupName = []
    elif isinstance(val, list):
      r:List[FunctionalFeedingGroupName] = []
      for x in val:
        r.append(FunctionalFeedingGroupName(x))
      self.__functionalFeedingGroupName = r
    else:
      self.__functionalFeedingGroupName = [FunctionalFeedingGroupName(val)]

  @property
  def taxonomicDetailsCitation(self) -> BibliographicReference:
    return self.__taxonomicDetailsCitation
  @taxonomicDetailsCitation.setter
  def taxonomicDetailsCitation(self, val:BibliographicReference) -> None:
    self.__taxonomicDetailsCitation = None if val is None else BibliographicReference(val)

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

    with tag(name):
      if self.__cellFormName is not None:
        line('CellFormName', self.__cellFormName)
      if self.__cellShapeName is not None:
        line('CellShapeName', self.__cellShapeName)
      if len(self.__habitName) > 3:
        raise WQXException("Attribute 'habitName' must be a list of 0 to 3 HabitName objects.")
      for x in self.__habitName:
        line('HabitName', x)
      if self.__voltinismName is not None:
        line('VoltinismName', self.__voltinismName)
      if self.__taxonomicPollutionTolerance is not None:
        line('TaxonomicPollutionTolerance', self.__taxonomicPollutionTolerance)
      if self.__taxonomicPollutionToleranceScaleText is not None:
        line('TaxonomicPollutionToleranceScaleText', self.__taxonomicPollutionToleranceScaleText)
      if self.__trophicLevelName is not None:
        line('TrophicLevelName', self.__trophicLevelName)
      if len(self.__functionalFeedingGroupName) > 3:
        raise WQXException("Attribute 'functionalFeedingGroupName' must be a list of 0 to 3 FunctionalFeedingGroupName objects.")
      for x in self.__functionalFeedingGroupName:
        line('FunctionalFeedingGroupName', x)
      if self.__taxonomicDetailsCitation is not None:
        asis(self.__taxonomicDetailsCitation.generateXML('TaxonomicDetailsCitation'))

    return doc.getvalue()
