
package de.ivu.elect.exchange.person.mapper;

import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.image.entity.Bild;
import de.ivu.elect.business.person.entity.Geschlecht;
import de.ivu.elect.business.person.entity.Kontoverbindung;
import de.ivu.elect.business.person.entity.PersonStatus;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.PersonenregisterAbgleichStatus;
import de.ivu.elect.business.person.entity.SichtpruefungStatus;
import de.ivu.elect.business.person.entity.Sperrmerkmal;
import de.ivu.elect.business.person.entity.Wahlrechtsausschluss;
import de.ivu.elect.business.staat.entity.Staat;
import de.ivu.elect.exchange.EntityMapper;
import de.ivu.elect.exchange.anschrift.mapper.AnschriftMapper;
import de.ivu.elect.exchange.image.mapper.BildMapper;
import de.ivu.elect.exchange.staat.mapper.StaatMapper;
import de.ivu.elect.interfaces.core.Anschrift;
import de.ivu.elect.interfaces.core.Person;

public class PersonMapper {

  @Inject
  private transient AnschriftMapper anschriftMapper;

  @Inject
  private transient StaatMapper staatMapper;

  @Inject
  private transient BildMapper bildMapper;

  public PersonMapper() {
    super();
  }

  public PersonMapper(AnschriftMapper anschriftMapper, StaatMapper staatMapper, BildMapper bildMapper) {
    super();

    this.anschriftMapper = anschriftMapper;
    this.staatMapper = staatMapper;
    this.bildMapper = bildMapper;
  }

  public void extern(Personendaten source, Person target) {
    target.setId(EntityMapper.createIdInDatei(source));

    target.setAkademischerGrad(source.getAkademischerGradUnformatiert());
    target.setAnrede(source.getAnrede());
    extern(source.getAnschrift(), target.getAnschrift());
    extern(source.getErreichbarkeitsanschrift(), target.getErreichbarkeitsanschrift());
    target.setAuswaertig(Boolean.TRUE.equals(source.getAuswaertig()));

    target.setBemerkung(source.getBemerkung());
    target.setBeruf(source.getBerufUnformatiert());
    target.setBerufsschluessel(source.getBerufsschluessel());
    target.setBewertung(source.getBewertung());

    target.setCustomData(source.getCustomDataXml());

    target.setEhrenamt(source.getEhrenamtUnformatiert());
    target.setEmailAdresse(source.getEmailAdresse());
    target.setEmailAdresseArbeit(source.getEmailAdresseArbeit());
    target.setExterneId(source.getExterneId());
    target.setExternesOrdnungsmerkmal(source.getOrdnungsmerkmal());

    target.setFamilienname(source.getFamilienname());
    target.setNamensbestandteile(source.getFamiliennameBestandteil());
    target.setFaxnummer(source.getFaxnummer());
    target.setFoto(extern(source.getFoto()));

    target.setGeburtsdatum(source.getGeburtsdatum());
    target.setGeschlecht(extern(source.getGeschlecht()));
    target.setGeburtsort(source.getGeburtsort());

    extern(source.getKontoverbindung(), target.getKontoverbindung());
    target.setKuenstlername(source.getKuenstlername());

    target.setOrdensname(source.getOrdensname());

    target.setPersonendatenTags(source.getPersonendatenTagsSortiert());
    target.setPersonenregisterAbgleichStatus(extern(source.getPersonenregisterAbgleichStatus()));
    target.setPersonenregisterAbgleichZeitpunkt(source.getPersonenregisterAbgleichZeitpunkt());
    target.setPersonStatus(extern(source.getPersonStatus()));

    target.setVorname(source.getRufname());

    target.setSichtpruefungStatus(extern(source.getSichtpruefungStatus()));
    target.setSperrmerkmal(extern(source.getSperrmerkmal()));
    target.setStaatsangehoerigkeiten(extern(source.getStaatsangehoerigkeitenSorted()));
    target.setStaatsangehoerigkeitenSortOrder(source.getStaatsangehoerigkeitenSortOrder());
    target.setStimmbezirkSchluessel(source.getStimmbezirkSchluessel());

    target.setTelefonnummerArbeit(source.getTelefonnummerArbeit());
    target.setTelefonnummerFestnetz(source.getTelefonnummerFestnetz());
    target.setTelefonnummerMobil(source.getTelefonnummerMobil());
    target.setTitel(source.getTitel());

    target.setVornamenVollstaendig(source.getVornamen());

    target.setWahlrechtsausschluss(extern(source.getWahlrechtsausschluss()));

    target.setZuzugsdatumBund(source.getZuzugsdatumBund());
    target.setZuzugsdatumGemeinde(source.getZuzugsdatumGemeinde());
    target.setZuzugsdatumLand(source.getZuzugsdatumLand());
    target.setZuzugsdatumStadtbezirk(source.getZuzugsdatumStadtbezirk());
  }

  public void intern(Person source, Personendaten target) {
    target.setAkademischerGradUnformatiert(source.getAkademischerGrad());
    target.setAnrede(source.getAnrede());
    intern(source.getAnschrift(), target.getAnschrift());
    intern(source.getErreichbarkeitsanschrift(), target.getErreichbarkeitsanschrift());
    target.setAuswaertig(Boolean.TRUE.equals(source.getAuswaertig()));

    target.setBemerkung(source.getBemerkung());
    target.setBerufsschluessel(source.getBerufsschluessel());
    target.setBerufUnformatiert(source.getBeruf());
    target.setBewertung(source.getBewertung());

    if (isNotBlank(source.getCustomData())) {
      target.setCustomDataXml(source.getCustomData());
    }

    target.setEhrenamtUnformatiert(source.getEhrenamt());
    target.setEmailAdresse(source.getEmailAdresse());
    target.setEmailAdresseArbeit(source.getEmailAdresseArbeit());
    target.setExterneId(source.getExterneId());
    target.setExternesOrdnungsmerkmal(source.getExternesOrdnungsmerkmal());

    target.setFamilienname(source.getFamilienname());
    target.setFamiliennameBestandteil(source.getNamensbestandteile());
    target.setFaxnummer(source.getFaxnummer());
    target.setFoto(intern(source.getFoto()));

    target.setGeburtsdatum(source.getGeburtsdatum());
    target.setGeburtsort(source.getGeburtsort());
    target.setGeschlecht(intern(source.getGeschlecht()));

    intern(source.getKontoverbindung(), target.getKontoverbindung());
    target.setKuenstlername(source.getKuenstlername());

    target.setOrdensname(source.getOrdensname());

    source.getPersonendatenTags().forEach(target::addPersonendatenTag);
    target.setPersonenregisterAbgleichStatus(intern(source.getPersonenregisterAbgleichStatus()));
    target.setPersonenregisterAbgleichZeitpunkt(source.getPersonenregisterAbgleichZeitpunkt());
    target.setPersonStatus(intern(source.getPersonStatus()));

    target.setRufname(source.getVorname());

    target.setSichtpruefungStatus(intern(source.getSichtpruefungStatus()));
    target.setSperrmerkmal(intern(source.getSperrmerkmal()));
    target.setStaatsangehoerigkeitenSorted(intern(source.getStaatsangehoerigkeiten()));
    target.setStaatsangehoerigkeitenSortOrder(defaultIfBlank(source.getStaatsangehoerigkeitenSortOrder(), target.getStaatsangehoerigkeitenSortOrder()));
    target.setStimmbezirkSchluessel(source.getStimmbezirkSchluessel());

    target.setTelefonnummerArbeit(source.getTelefonnummerArbeit());
    target.setTelefonnummerFestnetz(source.getTelefonnummerFestnetz());
    target.setTelefonnummerMobil(source.getTelefonnummerMobil());
    target.setTitel(source.getTitel());

    target.setVornamen(source.getVornamenVollstaendig());

    target.setWahlrechtsausschluss(intern(source.getWahlrechtsausschluss()));

    target.setZuzugsdatumBund(source.getZuzugsdatumBund());
    target.setZuzugsdatumLand(source.getZuzugsdatumLand());
    target.setZuzugsdatumGemeinde(source.getZuzugsdatumGemeinde());
    target.setZuzugsdatumStadtbezirk(source.getZuzugsdatumStadtbezirk());
  }

  private void extern(de.ivu.elect.business.anschrift.entity.Anschrift source, Anschrift target) {
    anschriftMapper.extern(source, target);
  }

  private void intern(Anschrift source, de.ivu.elect.business.anschrift.entity.Anschrift target) {
    anschriftMapper.intern(source, target);
  }

  private void extern(Kontoverbindung source, de.ivu.elect.interfaces.core.Kontoverbindung target) {
    target.setBankleitzahl(source.getBankleitzahl());
    target.setBic(source.getBic());

    target.setIban(source.getIban());
    target.setIbanBearbeiter(source.getIbanBearbeiter());
    target.setIbanVorAenderung(source.getIbanVorAenderung());

    target.setKontoinhaber(source.getKontoinhaber());
    target.setKontonummer(source.getKontonummer());
    target.setKreditinstitut(source.getKreditinstitut());
  }

  private void intern(de.ivu.elect.interfaces.core.Kontoverbindung source, Kontoverbindung target) {
    target.setBankleitzahl(source.getBankleitzahl());
    target.setBic(source.getBic());

    target.setIban(source.getIban());
    target.setIbanBearbeiter(source.getIbanBearbeiter());
    target.setIbanVorAenderung(source.getIbanVorAenderung());

    target.setKontoinhaber(source.getKontoinhaber());
    target.setKontonummer(source.getKontonummer());
    target.setKreditinstitut(source.getKreditinstitut());
  }

  private List<Staat> intern(List<de.ivu.elect.interfaces.core.Staat> sources) {
    return new ArrayList<>(staatMapper.intern(sources));
  }

  private List<de.ivu.elect.interfaces.core.Staat> extern(List<Staat> sources) {
    return new ArrayList<>(staatMapper.extern(sources));
  }

  @Nullable
  private de.ivu.elect.interfaces.core.Bild extern(Bild source) {
    return bildMapper.extern(source);
  }

  @Nullable
  private Bild intern(de.ivu.elect.interfaces.core.Bild source) {
    return bildMapper.intern(source);
  }

  protected Geschlecht intern(de.ivu.elect.interfaces.core.Geschlecht source) {
    if (source == null) {
      return Geschlecht.UNBEKANNT;
    }

    return Geschlecht.valueOf(source.name());
  }

  protected de.ivu.elect.interfaces.core.Geschlecht extern(Geschlecht source) {
    return de.ivu.elect.interfaces.core.Geschlecht.valueOf(source.name());
  }

  protected PersonenregisterAbgleichStatus intern(de.ivu.elect.interfaces.core.PersonenregisterAbgleichStatus source) {
    if (source == null) {
      return PersonenregisterAbgleichStatus.KEIN_ABGLEICH_NOTWENDIG;
    }

    return PersonenregisterAbgleichStatus.valueOf(source.name());
  }

  protected de.ivu.elect.interfaces.core.PersonenregisterAbgleichStatus extern(PersonenregisterAbgleichStatus source) {
    return de.ivu.elect.interfaces.core.PersonenregisterAbgleichStatus.valueOf(source.name());
  }

  protected PersonStatus intern(de.ivu.elect.interfaces.core.PersonStatus source) {
    if (source == null) {
      return PersonStatus.NICHT_ZU_PRUEFEN;
    }

    return PersonStatus.valueOf(source.name());
  }

  protected de.ivu.elect.interfaces.core.PersonStatus extern(PersonStatus source) {
    return de.ivu.elect.interfaces.core.PersonStatus.valueOf(source.name());
  }

  protected SichtpruefungStatus intern(de.ivu.elect.interfaces.core.SichtpruefungStatus source) {
    if (source == null) {
      return SichtpruefungStatus.KEINE_SICHTPRUEFUNG_NOTWENDIG;
    }

    return SichtpruefungStatus.valueOf(source.name());
  }

  protected de.ivu.elect.interfaces.core.SichtpruefungStatus extern(SichtpruefungStatus source) {
    return de.ivu.elect.interfaces.core.SichtpruefungStatus.valueOf(source.name());
  }

  protected Sperrmerkmal intern(de.ivu.elect.interfaces.core.Sperrmerkmal source) {
    if (source == null) { // NOTE, dass aufgrund der Abwärtskompatibilität das Sperrmerkmal optional definiert ist.
      return Sperrmerkmal.UNBEKANNT;
    }

    return Sperrmerkmal.valueOf(source.name());
  }

  protected de.ivu.elect.interfaces.core.Sperrmerkmal extern(Sperrmerkmal source) {
    return de.ivu.elect.interfaces.core.Sperrmerkmal.valueOf(source.name());
  }

  protected Wahlrechtsausschluss intern(de.ivu.elect.interfaces.core.Wahlrechtsausschluss source) {
    if (source == null) { // NOTE, dass aufgrund der Abwärtskompatibilität der Wahlrechtsausschluss optional definiert ist.
      return Wahlrechtsausschluss.UNBEKANNT;
    }

    return Wahlrechtsausschluss.valueOf(source.name());
  }

  protected de.ivu.elect.interfaces.core.Wahlrechtsausschluss extern(Wahlrechtsausschluss source) {
    return de.ivu.elect.interfaces.core.Wahlrechtsausschluss.valueOf(source.name());
  }
}
