
package de.ivu.elect.business.wahlrechtspruefung.control;

import static de.ivu.elect.jee.entity.EntityUtil.castTo;

import java.io.Serializable;
import java.util.Comparator;

import de.ivu.elect.business.kandidatur.control.ListenkandidaturByEingereichtePositionComparator;
import de.ivu.elect.business.kandidatur.control.ListenkandidaturByRelativePositionComparator;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.wahlrechtspruefung.entity.Pruefkriterium;
import de.ivu.elect.business.wahlrechtspruefung.entity.Wahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.control.WahlvorschlagByRelativePositionAndGruppeSchluesselComparator;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.util.NullComparator;

public class WahlrechtspruefungComparator implements Comparator<Wahlrechtspruefung>, Serializable {

  private static final long serialVersionUID = 1L;

  private static final Comparator<Object> NULL_COMPARATOR = NullComparator.NON_NULL_BEFORE_NULL_COMPARATOR;

  private static final Comparator<Wahlvorschlag> WAHLVORSCHLAG_COMPARATOR = new WahlvorschlagByRelativePositionAndGruppeSchluesselComparator();

  private static final Comparator<Listenkandidatur> LISTENKANDIDATUR_COMPARATOR = new ListenkandidaturByRelativePositionComparator()
      .thenComparing(new ListenkandidaturByEingereichtePositionComparator());

  private static final Comparator<Pruefkriterium> PRUEFKRITERIUM_COMPARATOR = new PruefkriteriumByPositionComparator();

  public WahlrechtspruefungComparator() {
    super();
  }

  @Override
  public int compare(Wahlrechtspruefung one, Wahlrechtspruefung another) {
    if (one == null || another == null) {
      return NULL_COMPARATOR.compare(one, another);
    }

    int comparedByWahlvorschlag = compareByWahlvorschlag(one.getWahlvorschlag(), another.getWahlvorschlag());

    if (comparedByWahlvorschlag == 0) {
      int comparedByKandidatur = compareByKandidatur(one.getKandidatur(), another.getKandidatur());

      if (comparedByKandidatur == 0) {
        int comparedByPruefkriterium = compareByPruefkriterium(one.getPruefkriterium(), another.getPruefkriterium());

        if (comparedByPruefkriterium == 0) {
          return one.getPk().compareTo(another.getPk());
        }

        return comparedByPruefkriterium;
      }

      return comparedByKandidatur;
    }

    return comparedByWahlvorschlag;
  }

  private int compareByWahlvorschlag(Wahlvorschlag one, Wahlvorschlag another) {
    return WAHLVORSCHLAG_COMPARATOR.compare(one, another);
  }

  private int compareByKandidatur(Kandidatur one, Kandidatur another) {
    if (one == null || another == null) {
      return NULL_COMPARATOR.compare(one, another);
    }

    if (one.isInstanceOf(Listenkandidatur.class)) {
      if (another.isInstanceOf(Listenkandidatur.class)) {
        return LISTENKANDIDATUR_COMPARATOR.compare(castTo(one, Listenkandidatur.class), castTo(another, Listenkandidatur.class));
      }

      return -1;
    }

    if (another.isInstanceOf(Listenkandidatur.class)) {
      return 1;
    }

    return one.getPk().compareTo(another.getPk());
  }

  private int compareByPruefkriterium(Pruefkriterium one, Pruefkriterium another) {
    return PRUEFKRITERIUM_COMPARATOR.compare(one, another);
  }
}
