
package de.ivu.elect.presentation.personenpruefung.form;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.inject.Inject;

import de.ivu.elect.business.anschrift.entity.Anschrift;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.personenregister.entity.PersonenregisterAnschrift;
import de.ivu.elect.business.personenregister.entity.PersonenregisterAnschriftProperties;
import de.ivu.elect.business.personenregister.entity.PersonenregisterPersonendaten;
import de.ivu.elect.business.personenregister.entity.PersonenregisterPersonendatenProperties;
import de.ivu.elect.business.staat.boundary.StaatExtendedDAO;
import de.ivu.elect.business.staat.boundary.StaatFinder;
import de.ivu.elect.business.staat.entity.Staat;
import de.ivu.elect.jee.presentation.dynamicform.Property;


import static java.util.Arrays.asList;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

public class PersonenKonfliktPersonenregisterAbgleichAufloesenViewFormData implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient StaatExtendedDAO staatExtendedDAO;

  @Inject
  private transient StaatFinder staatFinder;

  private Personendaten tmpPersonendaten;

  private PersonenregisterPersonendaten personenregisterPersonendaten;

  public PersonenKonfliktPersonenregisterAbgleichAufloesenViewFormData() {
    super();
  }

  public Personendaten getTmpPersonendaten() {
    return tmpPersonendaten;
  }

  public void setTmpPersonendaten(Personendaten tmpPersonendaten) {
    this.tmpPersonendaten = tmpPersonendaten;

    if (this.tmpPersonendaten != null) { // Eager-Loading...
      this.tmpPersonendaten.getKontoverbindung().getIban();

      for (Staat staatsangehoerigkeit : this.tmpPersonendaten.getStaatsangehoerigkeitenSorted()) {
        staatsangehoerigkeit.getCustomDataXml();
      }

      for (Anschrift anschrift : asList(this.tmpPersonendaten.getAnschrift(), this.tmpPersonendaten.getErreichbarkeitsanschrift())) {
        // ELECTDD-697 kann in DD aus "historischen Gründen" null sein, da da
        if (anschrift != null) {
          anschrift.getCustomDataXml();
        }
      }
    }
  }

  protected Anschrift getTmpAnschrift() {
    return getTmpPersonendaten().getAnschrift();
  }

  public PersonenregisterPersonendaten getPersonenregisterPersonendaten() {
    return personenregisterPersonendaten;
  }

  protected PersonenregisterAnschrift getPersonenregisterAnschrift() {
    return getPersonenregisterPersonendaten().getAnschrift();
  }

  public void setPersonenregisterPersonendaten(PersonenregisterPersonendaten personenregisterPersonendaten) {
    this.personenregisterPersonendaten = personenregisterPersonendaten;
  }

  public void applyTmpPersonendaten(Personendaten to) {
    copyTmpPersonendatenToEntity(getTmpPersonendaten(), to);
    copyTmpAnschriftToEntity(getTmpAnschrift(), to.getAnschrift());
  }

  protected void copyTmpPersonendatenToEntity(Personendaten from, Personendaten to) {
    to.setOrdnungsmerkmal(from.getOrdnungsmerkmal());

    to.setAnrede(from.getAnrede());
    to.setTitel(from.getTitel());

    to.setFamilienname(from.getFamilienname());
    to.setFamiliennameBestandteil(from.getFamiliennameBestandteil());

    to.setRufname(from.getRufname());
    to.setVornamen(from.getVornamen());

    to.setKuenstlername(from.getKuenstlername());
    to.setOrdensname(from.getOrdensname());

    to.setGeburtsdatum(from.getGeburtsdatum());
    to.setGeburtsort(from.getGeburtsort());
    to.setGeschlecht(from.getGeschlecht());

    to.setStaatsangehoerigkeitenSorted(from.getStaatsangehoerigkeitenSorted());

    to.setWahlrechtsausschluss(from.getWahlrechtsausschluss());
    to.setStimmbezirkSchluessel(from.getStimmbezirkSchluessel());

    to.setZuzugsdatumBund(from.getZuzugsdatumBund());
    to.setZuzugsdatumLand(from.getZuzugsdatumLand());
    to.setZuzugsdatumGemeinde(from.getZuzugsdatumGemeinde());
    to.setZuzugsdatumStadtbezirk(from.getZuzugsdatumStadtbezirk());
  }

  protected void copyTmpAnschriftToEntity(Anschrift from, Anschrift to) {
    to.setAnschriftArt(from.getAnschriftArt());

    to.setStrasse(from.getStrasse());
    to.setHausnummer(from.getHausnummer());
    to.setHausnummerzusatz(from.getHausnummerzusatz());
    to.setWohnungsnummer(from.getWohnungsnummer());

    to.setPlz(from.getPlz());
    to.setOrt(from.getOrt());
    to.setOrtsteil(from.getOrtsteil());

    to.setStaat(from.getStaat());

    to.setZustellanweisung(from.getZustellanweisung());
  }

  public void applyPersonenregisterPersonendaten() {
    copyPersonenregisterPersonendatenToTmpPersonendaten(getPersonenregisterPersonendaten(), getTmpPersonendaten());
    copyPersonenregisterAnschriftToTmpAnschrift(getPersonenregisterAnschrift(), getTmpAnschrift());
  }

  protected void copyPersonenregisterPersonendatenToTmpPersonendaten(PersonenregisterPersonendaten from, Personendaten to) {
    applyOrdnungsmerkmal(from, to);

    applyAnrede(from, to);
    applyTitel(from, to);

    applyFamiliennameBestandteil(from, to);
    applyFamilienname(from, to);

    applyRufname(from, to);
    applyVornamen(from, to);

    applyKuenstlername(from, to);
    applyOrdensname(from, to);

    applyGeburtsdatum(from, to);
    applyGeburtsort(from, to);
    applyGeschlecht(from, to);

    applyStaatsangehoerigkeiten(from, to);

    applyWahlrechtsausschluss(from, to);
    applyStimmbezirkSchluessel(from, to);

    applyZuzugsdatumBund(from, to);
    applyZuzugsdatumLand(from, to);
    applyZuzugsdatumGemeinde(from, to);
    applyZuzugsdatumStadtbezirk(from, to);
  }

  protected void copyPersonenregisterAnschriftToTmpAnschrift(PersonenregisterAnschrift from, Anschrift to) {
    applyAnschriftArt(from, to);

    applyStrasse(from, to);
    applyHausnummer(from, to);
    applyHausnummerzusatz(from, to);
    applyWohnungsnummer(from, to);

    applyPlz(from, to);
    applyOrt(from, to);
    applyOrtsteil(from, to);

    applyStaat(from, to);

    applyZustellanweisung(from, to);
  }

  public void applyPersonenregisterPersonendatum(Property property) {
    copyPersonenregisterPersonendatenAttributeToTmpPersonendatenAttribute(property, getPersonenregisterPersonendaten(), getTmpPersonendaten());
    copyPersonenregisterAnschriftAttributeToTmpAnschriftAttribute(property, getPersonenregisterAnschrift(), getTmpAnschrift());
  }

  protected void copyPersonenregisterPersonendatenAttributeToTmpPersonendatenAttribute(Property property, PersonenregisterPersonendaten from, Personendaten to) {
    if (isOrdnungsmerkmalProperty(property)) {
      applyOrdnungsmerkmal(from, to);
    } else if (isAnredeProperty(property)) {
      applyAnrede(from, to);
    } else if (isTitelProperty(property)) {
      applyTitel(from, to);
    } else if (isFamiliennameBestandteilProperty(property)) {
      applyFamiliennameBestandteil(from, to);
    } else if (isFamiliennameProperty(property)) {
      applyFamilienname(from, to);
    } else if (isRufnameProperty(property)) {
      applyRufname(from, to);
    } else if (isVornamenProperty(property)) {
      applyVornamen(from, to);
    } else if (isKuenstlernameProperty(property)) {
      applyKuenstlername(from, to);
    } else if (isOrdensnameProperty(property)) {
      applyOrdensname(from, to);
    } else if (isGeburtsdatumProperty(property)) {
      applyGeburtsdatum(from, to);
    } else if (isGeburtsortProperty(property)) {
      applyGeburtsort(from, to);
    } else if (isGeschlechtProperty(property)) {
      applyGeschlecht(from, to);
    } else if (isStaatsangehoerigkeitProperty(property)) {
      applyStaatsangehoerigkeiten(from, to);
    } else if (isWahlrechtsausschlussProperty(property)) {
      applyWahlrechtsausschluss(from, to);
    } else if (isZuzugsdatumBundProperty(property)) {
      applyZuzugsdatumBund(from, to);
    } else if (isZuzugsdatumLandProperty(property)) {
      applyZuzugsdatumLand(from, to);
    } else if (isZuzugsdatumGemeindeProperty(property)) {
      applyZuzugsdatumGemeinde(from, to);
    } else if (isZuzugsdatumStadtbezirkProperty(property)) {
      applyZuzugsdatumStadtbezirk(from, to);
    } else if (isStimmbezirkSchluesselProperty(property)) {
      applyStimmbezirkSchluessel(from, to);
    }
  }

  protected void copyPersonenregisterAnschriftAttributeToTmpAnschriftAttribute(Property property, PersonenregisterAnschrift from, Anschrift to) {
    if (isAnschriftArtProperty(property)) {
      applyAnschriftArt(from, to);
    } else if (isPlzProperty(property)) {
      applyPlz(from, to);
    } else if (isOrtProperty(property)) {
      applyOrt(from, to);
    } else if (isOrtsteilProperty(property)) {
      applyOrtsteil(from, to);
    } else if (isStrasseProperty(property)) {
      applyStrasse(from, to);
    } else if (isHausnummerProperty(property)) {
      applyHausnummer(from, to);
    } else if (isHausnummerzusatzProperty(property)) {
      applyHausnummerzusatz(from, to);
    } else if (isWohnungsnummerProperty(property)) {
      applyWohnungsnummer(from, to);
    } else if (isZustellanweisungProperty(property)) {
      applyZustellanweisung(from, to);
    } else if (isStaatProperty(property)) {
      applyStaat(from, to);
    }
  }

  protected boolean isOrdnungsmerkmalProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.OrdnungsmerkmalProperty;
  }

  protected void applyOrdnungsmerkmal(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getOrdnungsmerkmal())) {
      to.setOrdnungsmerkmal(from.getOrdnungsmerkmal());
    }
  }

  protected boolean isAnredeProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.AnredeProperty;
  }

  protected void applyAnrede(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getAnrede())) {
      to.setAnrede(from.getAnrede());
    }
  }

  protected boolean isTitelProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.TitelProperty;
  }

  protected void applyTitel(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getTitel())) {
      to.setTitel(from.getTitel());
    }
  }

  protected boolean isFamiliennameBestandteilProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.FamiliennameBestandteilProperty;
  }

  protected void applyFamiliennameBestandteil(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getFamiliennameBestandteil())) {
      to.setFamiliennameBestandteil(from.getFamiliennameBestandteil());
    }
  }

  protected boolean isFamiliennameProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.FamiliennameProperty;
  }

  protected void applyFamilienname(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getFamilienname())) {
      to.setFamilienname(from.getFamilienname());
    }
  }

  protected boolean isRufnameProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.RufnameProperty;
  }

  protected void applyRufname(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getRufname())) {
      to.setRufname(from.getRufname());
    }
  }

  protected boolean isVornamenProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.VornamenProperty;
  }

  protected void applyVornamen(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getVornamen())) {
      to.setVornamen(from.getVornamen());
    }
  }

  protected boolean isKuenstlernameProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.KuenstlernameProperty;
  }

  protected void applyKuenstlername(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getKuenstlername())) {
      to.setKuenstlername(from.getKuenstlername());
    }
  }

  protected boolean isOrdensnameProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.OrdensnameProperty;
  }

  protected void applyOrdensname(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getOrdensname())) {
      to.setOrdensname(from.getOrdensname());
    }
  }

  protected boolean isGeburtsdatumProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.GeburtsdatumProperty;
  }

  protected void applyGeburtsdatum(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getGeburtsdatum() != null) {
      to.setGeburtsdatum(from.getGeburtsdatum());
    }
  }

  protected boolean isGeburtsortProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.GeburtsortProperty;
  }

  protected void applyGeburtsort(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getGeburtsort())) {
      to.setGeburtsort(from.getGeburtsort());
    }
  }

  protected boolean isGeschlechtProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.GeschlechtProperty;
  }

  protected void applyGeschlecht(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getGeschlecht() != null) {
      to.setGeschlecht(from.getGeschlecht());
    }
  }

  protected boolean isStaatsangehoerigkeitProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.NameOrCodeStaatsangehoerigkeitProperty;
  }

  protected void applyStaatsangehoerigkeiten(PersonenregisterPersonendaten from, Personendaten to) {
    to.setStaatsangehoerigkeitenSorted(tryFindStaatsangehoerigkeiten(from.getStaatsangehoerigkeiten()));
  }

  protected List<Staat> tryFindStaatsangehoerigkeiten(List<String> staatsangehoerigkeiten) {
    return staatsangehoerigkeiten.stream() //
        .map(staatsangehoerigkeit -> staatFinder.tryFindUniqueStaat(staatExtendedDAO, staatsangehoerigkeit)) //
        .filter(Objects::nonNull) //
        .collect(Collectors.toList());
  }

  protected boolean isWahlrechtsausschlussProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.WahlrechtsausschlussProperty;
  }

  protected void applyWahlrechtsausschluss(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getWahlrechtsausschluss() != null) {
      to.setWahlrechtsausschluss(from.getWahlrechtsausschluss());
    }
  }

  protected boolean isZuzugsdatumBundProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.ZuzugsdatumBundProperty;
  }

  protected void applyZuzugsdatumBund(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getZuzugsdatumBund() != null) {
      to.setZuzugsdatumBund(from.getZuzugsdatumBund());
    }
  }

  protected boolean isZuzugsdatumLandProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.ZuzugsdatumLandProperty;
  }

  protected void applyZuzugsdatumLand(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getZuzugsdatumLand() != null) {
      to.setZuzugsdatumLand(from.getZuzugsdatumLand());
    }
  }

  protected boolean isZuzugsdatumGemeindeProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.ZuzugsdatumGemeindeProperty;
  }

  protected void applyZuzugsdatumGemeinde(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getZuzugsdatumGemeinde() != null) {
      to.setZuzugsdatumGemeinde(from.getZuzugsdatumGemeinde());
    }
  }

  protected boolean isZuzugsdatumStadtbezirkProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.ZuzugsdatumStadtbezirkProperty;
  }

  protected void applyZuzugsdatumStadtbezirk(PersonenregisterPersonendaten from, Personendaten to) {
    if (from.getZuzugsdatumStadtbezirk() != null) {
      to.setZuzugsdatumStadtbezirk(from.getZuzugsdatumStadtbezirk());
    }
  }

  protected boolean isStimmbezirkSchluesselProperty(Property property) {
    return property instanceof PersonenregisterPersonendatenProperties.StimmbezirkSchluesselProperty;
  }

  protected void applyStimmbezirkSchluessel(PersonenregisterPersonendaten from, Personendaten to) {
    if (isNotBlank(from.getStimmbezirkSchluessel())) {
      to.setStimmbezirkSchluessel(from.getStimmbezirkSchluessel());
    }
  }

  protected boolean isAnschriftArtProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.AnschriftArtProperty;
  }

  protected void applyAnschriftArt(PersonenregisterAnschrift from, Anschrift to) {
    if (from.getAnschriftArt() != null) {
      to.setAnschriftArt(from.getAnschriftArt());
    }
  }

  protected boolean isOrtProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.OrtProperty;
  }

  protected void applyOrt(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getOrt())) {
      to.setOrt(from.getOrt());
    }
  }

  protected boolean isOrtsteilProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.OrtsteilProperty;
  }

  protected void applyOrtsteil(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getOrtsteil())) {
      to.setOrtsteil(from.getOrtsteil());
    }
  }

  protected boolean isPlzProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.PlzProperty;
  }

  protected void applyPlz(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getPlz())) {
      to.setPlz(from.getPlz());
    }
  }

  protected boolean isStrasseProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.StrasseProperty;
  }

  protected void applyStrasse(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getStrasse())) {
      to.setStrasse(from.getStrasse());
    }
  }

  protected boolean isHausnummerProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.HausnummerProperty;
  }

  protected void applyHausnummer(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getHausnummer())) {
      to.setHausnummer(from.getHausnummer());
    }
  }

  protected boolean isHausnummerzusatzProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.HausnummerzusatzProperty;
  }

  protected void applyHausnummerzusatz(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getHausnummerzusatz())) {
      to.setHausnummerzusatz(from.getHausnummerzusatz());
    }
  }

  protected boolean isWohnungsnummerProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.WohnungsnummerProperty;
  }

  protected void applyWohnungsnummer(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getWohnungsnummer())) {
      to.setWohnungsnummer(from.getWohnungsnummer());
    }
  }

  protected boolean isZustellanweisungProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.ZustellanweisungProperty;
  }

  protected void applyZustellanweisung(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getZustellanweisung())) {
      to.setZustellanweisung(from.getZustellanweisung());
    }
  }

  protected boolean isStaatProperty(Property property) {
    return property instanceof PersonenregisterAnschriftProperties.NameOrCodeStaatProperty;
  }

  protected void applyStaat(PersonenregisterAnschrift from, Anschrift to) {
    if (isNotBlank(from.getStaat())) {
      to.setStaat(from.getStaat());
    }
  }
}
