package de.ivu.elect.nl.eml.readable;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Element;

import de.ivu.elect.jee.exchange.JAXBUtil;
import de.ivu.elect.nl.eml.XmlHelper;
import de.ivu.wahl.wus.oasis.eml.AffiliationIdentifierStructure;
import de.ivu.wahl.wus.oasis.eml.CandidateList;
import de.ivu.wahl.wus.oasis.eml.ObjectFactory;
import de.ivu.wahl.wus.oasis.eml.kiesraad.ListData;
import de.ivu.wahl.wus.oasis.eml.kiesraad.PublicationLanguageType;


import static java.util.stream.Collectors.collectingAndThen;

public class AffiliationWrapper extends AbstractWrapper<CandidateList.Election.Contest.Affiliation> {

  public AffiliationWrapper() {
    super(new ObjectFactory().createCandidateListElectionContestAffiliation());
  }

  protected AffiliationWrapper(CandidateList.Election.Contest.Affiliation content) {
    super(content);
  }

  private AffiliationIdentifierStructure getAffiliationIdentifier() {
    if (getContent().getAffiliationIdentifier() == null) {
      getContent().setAffiliationIdentifier(of.createAffiliationIdentifierStructure());
    }
    return getContent().getAffiliationIdentifier();
  }

  public String getId() {
    return getAffiliationIdentifier().getId();
  }

  public void setId(String id) {
    getAffiliationIdentifier().setId(id);
  }

  public String getRegisteredName() {
    return getAffiliationIdentifier().getRegisteredName();
  }

  public void setRegisteredName(String registeredName) {
    getAffiliationIdentifier().setRegisteredName(registeredName);
  }

  private transient ListData listDataReadOnly = null;

  private ListData getListDataReadOnly() {
    if (listDataReadOnly == null) {
      // EML ist der größte *** überhaupt - vor allem in der "Kiesraad-Version"
      for (Object o : getContent().getAny()) {
        if (o instanceof Element) {
          Element e = (Element) o;
          if (StringUtils.isNotBlank(e.getTagName()) && e.getTagName().contains("ListData")) {
            String xmlString = XmlHelper.elementToString(e);
            try {
              listDataReadOnly = new JAXBUtil().unmarshal(ListData.class, new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
              break;
            } catch (Exception ex) {
              throw new RuntimeException(ex.getMessage(), ex);
            }
          }
        }
      }
    }
    if (listDataReadOnly == null) {
      listDataReadOnly = new ListData();// Null-Element
    }
    return listDataReadOnly;
  }

  protected void setListData(ListData listData) {
    // EML -Argghhh!!!
    JAXBElement<ListData> listDataJAXBElement = new JAXBElement<>(new QName("http://www.kiesraad.nl/extensions", "ListData"), ListData.class, listData);
    getContent().getAny().clear();
    getContent().getAny().add(listDataJAXBElement);
    listDataReadOnly = listData;
  }

  public boolean isPublishGender() {
    return getListDataReadOnly().isPublishGender();
  }

  public void setPublishGender(boolean publishGender) {
    ListData listDataReadOnly = getListDataReadOnly();
    listDataReadOnly.setPublishGender(publishGender);
    setListData(listDataReadOnly);
  }

  public PublicationLanguageType getPublicationLanguageType() {
    return getListDataReadOnly().getPublicationLanguage();
  }

  public void setPublicationLanguageType(PublicationLanguageType publicationLanguageType) {
    ListData listDataReadOnly = getListDataReadOnly();
    listDataReadOnly.setPublicationLanguage(publicationLanguageType);
    setListData(listDataReadOnly);
  }

  public BigInteger getBelongsToSet() {
    return getListDataReadOnly().getBelongsToSet();
  }

  public void setBelongsToSet(BigInteger belongsToSet) {
    ListData listDataReadOnly = getListDataReadOnly();
    listDataReadOnly.setBelongsToSet(belongsToSet);
    setListData(listDataReadOnly);
  }

  public String getBelongsToCombination() {
    return getListDataReadOnly().getBelongsToCombination();
  }

  public void setBelongsToCombination(String belongsToCombination) {
    ListData listDataReadOnly = getListDataReadOnly();
    listDataReadOnly.setBelongsToCombination(belongsToCombination);
    setListData(listDataReadOnly);
  }

  public ListSubmissionMode getListSubMissionMode() {
    return ListSubmissionMode.from(getContent().getType());
  }

  public void setListSubMissionMode(ListSubmissionMode listSubMissionMode) {
    getContent().setType(listSubMissionMode.getValue());
  }

  public List<Eml230CandidateWrapper> getCandidate() {
    return getContent().getCandidate().stream().map(Eml230CandidateWrapper::new).collect(collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
  }

  public Eml230CandidateWrapper addCandidate() {
    Eml230CandidateWrapper result = new Eml230CandidateWrapper();
    getContent().getCandidate().add(result.getContent());
    return result;
  }

}
