
package de.ivu.elect.business.person.entity;

import static java.util.Arrays.asList;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public abstract class AbstractPersonenVerknuepfung implements PersonenVerknuepfungBase {

  private static final long serialVersionUID = 1L;

  public static final VerknuepfungsGrundlage VERKNUEPFUNGS_GRUNDLAGE_POTENZIELLE_DUBLETTE = VerknuepfungsGrundlage.MASCHINELL;

  public static final VerknuepfungsStatus VERKNUEPFUNGS_STATUS_POTENZIELLE_DUBLETTE = VerknuepfungsStatus.AEHNLICH;

  public AbstractPersonenVerknuepfung() {
    super();
  }

  public boolean isIdentisch() {
    return VerknuepfungsStatus.IDENTISCH.equals(getVerknuepfungsStatus());
  }

  public boolean isAehnlich() {
    return VerknuepfungsStatus.AEHNLICH.equals(getVerknuepfungsStatus());
  }

  public boolean isVerschieden() {
    return VerknuepfungsStatus.VERSCHIEDEN.equals(getVerknuepfungsStatus());
  }

  public boolean isMaschinellVerknuepft() {
    return VerknuepfungsGrundlage.MASCHINELL.equals(getVerknuepfungsGrundlage());
  }

  public boolean isManuellVerknuepft() {
    return VerknuepfungsGrundlage.MANUELL.equals(getVerknuepfungsGrundlage());
  }

  public Personendaten getOther(Personendaten person) {
    if (person != null) {
      if (Objects.equals(getPerson1(), person)) {
        return getPerson2();
      }

      if (Objects.equals(getPerson2(), person)) {
        return getPerson1();
      }
    }

    throw new IllegalArgumentException("Die Person [" + person + "] ist nicht Teil der Verknüpfung [" + this + "]!");
  }

  public PersonendatenPK getPk1() {
    return getPerson1().getPk();
  }

  public PersonendatenPK getPk2() {
    return getPerson2().getPk();
  }

  public List<Personendaten> getPersonen() {
    return asList(getPerson1(), getPerson2());
  }

  /**
   * Setzt zwei Personendaten so, dass der kleinere PK in Person1 und der größere PK in Person2 steht, damit kann der unique-index sinnvoll verwendet werden
   */
  public void setPersonen(Personendaten one, Personendaten another) {
    setPerson1(selectPersonendaten1(one, another));
    setPerson2(selectPersonendaten2(one, another));
  }

  public void removePersonen() {
    getPerson1().removePersonenVerknuepfungByPerson1((PersonenVerknuepfung) this);
    getPerson2().removePersonenVerknuepfungByPerson2((PersonenVerknuepfung) this);
  }

  public PersonendatenPairKey getPersonendatenPairKey() {
    return new PersonendatenPairKey(getPerson1(), getPerson2());
  }

  public static Map<PersonendatenPairKey, PersonenVerknuepfung> mappePersonenVerknuepfungenNachPersonendatenPairKey(Collection<PersonenVerknuepfung> personenVerknuepfungen) {
    Map<PersonendatenPairKey, PersonenVerknuepfung> result = new HashMap<>();

    for (PersonenVerknuepfung personenVerknuepfung : personenVerknuepfungen) {
      result.put(personenVerknuepfung.getPersonendatenPairKey(), personenVerknuepfung);
    }

    return result;
  }

  private static Personendaten selectPersonendaten1(Personendaten one, Personendaten another) {
    if (one.getPk().compareTo(another.getPk()) < 0) {
      return one;
    }

    return another;
  }

  private static Personendaten selectPersonendaten2(Personendaten one, Personendaten another) {
    if (one.getPk().compareTo(another.getPk()) < 0) {
      return another;
    }

    return one;
  }
}
