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

import java.util.Collections;

import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;

import de.ivu.wahl.wus.oasis.eml.MailingAddressStructure;
import de.ivu.wahl.wus.oasis.eml.external.xnl.NameLineType;
import de.ivu.wahl.wus.oasis.eml.external.xnl.PersonName;
import de.ivu.wahl.wus.oasis.eml.external.xnl.PersonNameType;
import oasis.names.tc.ciq.xsdschema.xal._2.AddressDetails;
import oasis.names.tc.ciq.xsdschema.xal._2.Locality;
import oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory;

public abstract class AbstractEml230PersonWrapper<T> extends AbstractWrapper<T> {

  public static final String INITIALS = "Initials";

  protected AbstractEml230PersonWrapper(T content) {
    super(content);
  }

  @Nullable
  public String getFirstName() {
    if (getPersonName().getFirstName().isEmpty()) {
      return "";
    }
    return getPersonName().getFirstName().get(0).getContent();
  }

  public void setFirstName(String firstName) {
    getPersonName().getFirstName().clear();
    if (StringUtils.isNotBlank(firstName)) {
      getPersonName().getFirstName().add(new de.ivu.wahl.wus.oasis.eml.external.xnl.ObjectFactory().createPersonNameTypeFirstName());
      getPersonName().getFirstName().get(0).setContent(firstName);
    }
  }

  @Nullable
  public String getLastName() {
    if (getPersonName().getLastName().isEmpty()) {
      return null;
    }
    return getPersonName().getLastName().get(0).getContent();
  }

  public void setLastName(String lastName) {
    getPersonName().getLastName().clear();
    if (StringUtils.isNotBlank(lastName)) {
      getPersonName().getLastName().add(new de.ivu.wahl.wus.oasis.eml.external.xnl.ObjectFactory().createPersonNameTypeLastName());
      getPersonName().getLastName().get(0).setContent(lastName);
    }
  }

  public String getNamePrefix() {
    return getNamePrefixNode().getContent();
  }

  public void setNamePrefix(String namePrefix) {
    getPersonName().setNamePrefix(null);
    if (StringUtils.isNotBlank(namePrefix)) {
      getNamePrefixNode().setContent(namePrefix);
    }
  }

  protected abstract PersonName getPersonName();

  public void setMailing(String countryNameCode, String addressLine, String localityName, String postalcodeNumber) {

    // ELECTVAPP-1110
    MailingAddressStructure mailingAddress = getMailingAddress();

    Locality locality;
    if (StringUtils.isBlank(countryNameCode)) {
      mailingAddress.setCountry(null);
      if (mailingAddress.getLocality() == null) {
        mailingAddress.setLocality(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createLocality());
      }

      locality = mailingAddress.getLocality();
    } else {
      mailingAddress.setLocality(null);
      if (mailingAddress.getCountry() == null) {
        mailingAddress.setCountry(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createAddressDetailsCountry());
      }
      if (mailingAddress.getCountry().getLocality() == null) {
        mailingAddress.getCountry().setLocality(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createLocality());
      }

      if (mailingAddress.getCountry().getCountryNameCode().isEmpty()) {
        mailingAddress.getCountry().setCountryNameCode(Collections.singletonList(new ObjectFactory().createAddressDetailsCountryCountryNameCode()));
      }
      mailingAddress.getCountry().getCountryNameCode().get(0).setContent(countryNameCode);
      locality = mailingAddress.getCountry().getLocality();
    }

    locality.getAddressLine().clear();
    if (StringUtils.isNotBlank(addressLine)) {
      locality.getAddressLine().add(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createAddressLine());
      locality.getAddressLine().get(0).setContent(addressLine);
    }

    locality.getLocalityName().clear();
    locality.getLocalityName().add(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createLocalityLocalityName()); // ELECT-11628
    if (StringUtils.isNotBlank(localityName)) {
      locality.getLocalityName().get(0).setContent(localityName);
    }

    if (locality.getPostalCode() == null) {
      locality.setPostalCode(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createPostalCode());
    }
    locality.getPostalCode().getPostalCodeNumber().clear();
    if (StringUtils.isNotBlank(postalcodeNumber)) {
      locality.getPostalCode().getPostalCodeNumber().add(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createPostalCodePostalCodeNumber());
      locality.getPostalCode().getPostalCodeNumber().get(0).setContent(postalcodeNumber);
    } else {
      locality.setPostalCode(null); // ELECT-11946
    }


  }


  public String getMailingAddressLine() {
    return getMailing().getAddressLine().get(0).getContent();
  }


  public String getMailingLocalityName() {
    return getMailing().getLocalityName().get(0).getContent();
  }


  public String getMailingPostalCodeNumber() {
    return getMailing().getPostalCode().getPostalCodeNumber().get(0).getContent();
  }


  public String getMailingCountryNameCode() {
    return getCountryNameCodeFromCountry(getMailingAddress().getCountry());
  }

  @Nullable
  public String getInitials() {
    if (getPersonName().getNameLine().isEmpty()) {
      return null;
    }
    return getPersonName().getNameLine().get(0).getContent();
  }

  public void setInitials(String initials) {
    getPersonName().getNameLine().clear();
    if (StringUtils.isNotBlank(initials)) {
      NameLineType nameLineType = new de.ivu.wahl.wus.oasis.eml.external.xnl.ObjectFactory().createNameLineType();
      nameLineType.setNameType(INITIALS);
      nameLineType.setContent(initials);
      getPersonName().getNameLine().add(nameLineType);
    }
  }

  @Nullable
  public abstract String getLocalityName();

  public abstract void setLocalityName(String localityName);



  private Locality getMailing() {
    MailingAddressStructure mailingAddress = getMailingAddress();

    if (mailingAddress.getLocality() == null) {
      if (mailingAddress.getCountry() != null && mailingAddress.getCountry().getLocality() != null) {
        // NOTE: Bei ausländischen Anschriften befindet sich Locality in Country. Wir wollen aber immer das gleiche Locality verwenden.
        mailingAddress.setLocality(mailingAddress.getCountry().getLocality());
        mailingAddress.getCountry().setLocality(null);
      } else {
        Locality locality = new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createLocality();
        // ELECTVAPP-787 locality.setUsageType("internal"); //???
        mailingAddress.setLocality(locality);
      }
    }

    if (mailingAddress.getLocality().getAddressLine().isEmpty()) {
      mailingAddress.getLocality().getAddressLine()
          .add(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createAddressLine());
    }

    if (mailingAddress.getLocality().getLocalityName().isEmpty()) {
      mailingAddress.getLocality().getLocalityName()
          .add(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createLocalityLocalityName());
    }

    if (mailingAddress.getLocality().getPostalCode() == null) {
      mailingAddress.getLocality().setPostalCode(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createPostalCode());
    }
    if (mailingAddress.getLocality().getPostalCode().getPostalCodeNumber().isEmpty()) {
      mailingAddress.getLocality().getPostalCode().getPostalCodeNumber()
          .add(new oasis.names.tc.ciq.xsdschema.xal._2.ObjectFactory().createPostalCodePostalCodeNumber());
    }

    return mailingAddress.getLocality();
  }

  protected abstract MailingAddressStructure getMailingAddress();

  @Nullable
  protected String getCountryNameCodeFromCountry(AddressDetails.Country country) {
    if (country == null) {
      return null;
    }
    return country.getCountryNameCode().stream().findFirst().map(AddressDetails.Country.CountryNameCode::getContent).orElse(null);
  }

  protected PersonNameType.NamePrefix getNamePrefixNode() {
    if (getPersonName().getNamePrefix() == null) {
      getPersonName().setNamePrefix(new de.ivu.wahl.wus.oasis.eml.external.xnl.ObjectFactory().createPersonNameTypeNamePrefix());
    }
    return getPersonName().getNamePrefix();
  }

}