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

import java.util.Comparator;

import javax.annotation.Nullable;

import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagPK;
import de.ivu.elect.util.NullComparator;

public abstract class AbstractEntityAufStimmzettelStimmzettelPosition implements Comparable<AbstractEntityAufStimmzettelStimmzettelPosition> {

  public static final Comparator<Long> DEFAULT_POSITION_COMPARATOR = (one, another) -> {
    if (one == null || another == null) {
      // HINT: null tritt insb. auf, wenn der jeweilige Wahlvorschlag (noch) nicht zugelassen wurde.
      // NOTE, dass hier NICHT eine Exception geworfen werden sollte -- der Zulassungsstatus wird möglicherweise erst
      //       nach dem Sortieren (z.B. beim Iterieren über die sortierten Elemente) behandelt.
      return NullComparator.NON_NULL_BEFORE_NULL_COMPARATOR.compare(one, another);
    }

    return one.compareTo(another);
  };

  protected static final Long POSITION_EMPTY = null; // Legacy-Wert, erwartet bspw. in Tests!!!

  private final WahlvorschlagPK wahlvorschlagPK;

  private final Long eingereichtePosition;

  private final Long vorgegebenPosition;

  private final Long relativePosition;

  private final Long berechnetePosition;

  protected AbstractEntityAufStimmzettelStimmzettelPosition(WahlvorschlagPK wahlvorschlagPK, Long eingereichtePosition, Long vorgegebenPosition, Long relativePosition, Long berechnetePosition) {
    super();

    this.wahlvorschlagPK = wahlvorschlagPK;

    this.eingereichtePosition = eingereichtePosition;
    this.vorgegebenPosition = vorgegebenPosition;
    this.relativePosition = relativePosition;

    this.berechnetePosition = berechnetePosition;
  }

  /**
   * @return Die fest hinterlegte, vorläufige Stimmzettelposition (feste Ordnungszahl), die insbesondere auch für noch NICHT zugelassene Wahlvorschläge vergeben werden kann.
   */
  @Nullable
  public Long getPositionVorgegeben() {
    return getVorgegebenPosition(); // ELECTMUC-2790
  }

  public boolean hasPosition() {
    return getPosition() != null;
  }

  @Nullable
  public Long getPosition() {
    return getBerechnetePosition();
  }

  protected boolean hasBerechnetePosition() {
    return getBerechnetePosition() != null;
  }

  @Nullable
  protected Long getBerechnetePosition() {
    return berechnetePosition;
  }

  @Nullable
  protected Long getEingereichtePosition() {
    return eingereichtePosition;
  }

  @Nullable
  protected Long getVorgegebenPosition() {
    return vorgegebenPosition;
  }

  @Nullable
  protected Long getRelativePosition() {
    return relativePosition;
  }

  @Override
  public int compareTo(AbstractEntityAufStimmzettelStimmzettelPosition another) {
    return DEFAULT_POSITION_COMPARATOR.compare(getPosition(), another.getPosition());
  }

  /*
   * AUTO-GENERATED!!!
   */

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    Long position = getPosition();
    result = prime * result + (position == null ? 0 : position.hashCode());
    result = prime * result + (wahlvorschlagPK == null ? 0 : wahlvorschlagPK.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    AbstractEntityAufStimmzettelStimmzettelPosition other = (AbstractEntityAufStimmzettelStimmzettelPosition) obj;
    Long position = getPosition();
    if (position == null) {
      if (other.getPosition() != null) {
        return false;
      }
    } else if (!position.equals(other.getPosition())) {
      return false;
    }
    if (wahlvorschlagPK == null) {
      if (other.wahlvorschlagPK != null) {
        return false;
      }
    } else if (!wahlvorschlagPK.equals(other.wahlvorschlagPK)) {
      return false;
    }
    return true;
  }
}
