from ..exceptions import WQXException
from .AttachedBinaryObject import AttachedBinaryObject
from .ProjectMonitoringLocationWeighting import ProjectMonitoringLocationWeighting
from .SimpleContent import (
  ProjectDescriptionText,
  ProjectIdentifier,
  ProjectName,
  QAPPApprovalAgencyName,
  QAPPApprovedIndicator,
  SamplingDesignTypeCode
)
from typing import List, Union
from yattag import Doc

class Project:
  """An environmental data collection effort that has a stated purpose and puts a series of samples and results into a meaningful context."""

  __projectIdentifier: ProjectIdentifier
  __projectName: ProjectName
  __projectDescriptionText: ProjectDescriptionText
  __samplingDesignTypeCode: SamplingDesignTypeCode
  __qAPPApprovedIndicator: QAPPApprovedIndicator
  __qAPPApprovalAgencyName: QAPPApprovalAgencyName
  __attachedBinaryObject: List[AttachedBinaryObject]
  __projectMonitoringLocationWeighting: List[ProjectMonitoringLocationWeighting]

  def __init__(self, o=None, *,
    projectIdentifier:ProjectIdentifier = None,
    projectName:ProjectName = None,
    projectDescriptionText:ProjectDescriptionText = None,
    samplingDesignTypeCode:SamplingDesignTypeCode = None,
    qAPPApprovedIndicator:QAPPApprovedIndicator = None,
    qAPPApprovalAgencyName:QAPPApprovalAgencyName = None,
    attachedBinaryObject:List[AttachedBinaryObject] = None,
    projectMonitoringLocationWeighting:List[ProjectMonitoringLocationWeighting] = None
  ):
    if isinstance(o, Project):
      # Assign attributes from object without typechecking
      self.__projectIdentifier = o.projectIdentifier
      self.__projectName = o.projectName
      self.__projectDescriptionText = o.projectDescriptionText
      self.__samplingDesignTypeCode = o.samplingDesignTypeCode
      self.__qAPPApprovedIndicator = o.qAPPApprovedIndicator
      self.__qAPPApprovalAgencyName = o.qAPPApprovalAgencyName
      self.__attachedBinaryObject = o.attachedBinaryObject
      self.__projectMonitoringLocationWeighting = o.projectMonitoringLocationWeighting
    elif isinstance(o, dict):
      # Assign attributes from dictionary with typechecking
      self.projectIdentifier = o.get('projectIdentifier', default = None)
      self.projectName = o.get('projectName', default = None)
      self.projectDescriptionText = o.get('projectDescriptionText', default = None)
      self.samplingDesignTypeCode = o.get('samplingDesignTypeCode', default = None)
      self.qAPPApprovedIndicator = o.get('qAPPApprovedIndicator', default = None)
      self.qAPPApprovalAgencyName = o.get('qAPPApprovalAgencyName', default = None)
      self.attachedBinaryObject = o.get('attachedBinaryObject', default = None)
      self.projectMonitoringLocationWeighting = o.get('projectMonitoringLocationWeighting', default = None)
    else:
      # Assign attributes from named keywords with typechecking
      self.projectIdentifier = projectIdentifier
      self.projectName = projectName
      self.projectDescriptionText = projectDescriptionText
      self.samplingDesignTypeCode = samplingDesignTypeCode
      self.qAPPApprovedIndicator = qAPPApprovedIndicator
      self.qAPPApprovalAgencyName = qAPPApprovalAgencyName
      self.attachedBinaryObject = attachedBinaryObject
      self.projectMonitoringLocationWeighting = projectMonitoringLocationWeighting

  @property
  def projectIdentifier(self) -> ProjectIdentifier:
    return self.__projectIdentifier
  @projectIdentifier.setter
  def projectIdentifier(self, val:ProjectIdentifier) -> None:
    self.__projectIdentifier = ProjectIdentifier(val)

  @property
  def projectName(self) -> ProjectName:
    return self.__projectName
  @projectName.setter
  def projectName(self, val:ProjectName) -> None:
    self.__projectName = ProjectName(val)

  @property
  def projectDescriptionText(self) -> ProjectDescriptionText:
    return self.__projectDescriptionText
  @projectDescriptionText.setter
  def projectDescriptionText(self, val:ProjectDescriptionText) -> None:
    self.__projectDescriptionText = None if val is None else ProjectDescriptionText(val)

  @property
  def samplingDesignTypeCode(self) -> SamplingDesignTypeCode:
    return self.__samplingDesignTypeCode
  @samplingDesignTypeCode.setter
  def samplingDesignTypeCode(self, val:SamplingDesignTypeCode) -> None:
    self.__samplingDesignTypeCode = None if val is None else SamplingDesignTypeCode(val)

  @property
  def qAPPApprovedIndicator(self) -> QAPPApprovedIndicator:
    return self.__qAPPApprovedIndicator
  @qAPPApprovedIndicator.setter
  def qAPPApprovedIndicator(self, val:QAPPApprovedIndicator) -> None:
    self.__qAPPApprovedIndicator = None if val is None else QAPPApprovedIndicator(val)

  @property
  def qAPPApprovalAgencyName(self) -> QAPPApprovalAgencyName:
    return self.__qAPPApprovalAgencyName
  @qAPPApprovalAgencyName.setter
  def qAPPApprovalAgencyName(self, val:QAPPApprovalAgencyName) -> None:
    self.__qAPPApprovalAgencyName = None if val is None else QAPPApprovalAgencyName(val)

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

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

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

    with tag(name):
      if self.__projectIdentifier is None:
        raise WQXException("Attribute 'projectIdentifier' is required.")
      line('ProjectIdentifier', self.__projectIdentifier)
      if self.__projectName is None:
        raise WQXException("Attribute 'projectName' is required.")
      line('ProjectName', self.__projectName)
      if self.__projectDescriptionText is not None:
        line('ProjectDescriptionText', self.__projectDescriptionText)
      if self.__samplingDesignTypeCode is not None:
        line('SamplingDesignTypeCode', self.__samplingDesignTypeCode)
      if self.__qAPPApprovedIndicator is not None:
        line('QAPPApprovedIndicator', self.__qAPPApprovedIndicator)
      if self.__qAPPApprovalAgencyName is not None:
        line('QAPPApprovalAgencyName', self.__qAPPApprovalAgencyName)
      for x in self.__attachedBinaryObject:
        asis(x.generateXML('AttachedBinaryObject'))
      for x in self.__projectMonitoringLocationWeighting:
        asis(x.generateXML('ProjectMonitoringLocationWeighting'))

    return doc.getvalue()
