
package de.ivu.elect.core.exchange.gebietsbaum;

import java.util.Comparator;

import de.ivu.elect.business.gebietsbaum.control.GebietByPositionComparator;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.util.NullComparator;

public class GebietByErfassungsgebietsartAndPositionComparator<E extends Gebiet> implements Comparator<E> {

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

  private static final Comparator<Gebiet> GEBIET_BY_POSITION_COMPARATOR = GebietByPositionComparator.ASCENDING;

  public GebietByErfassungsgebietsartAndPositionComparator() {
    super();
  }

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

    int comparedByErfassungsgebietsart = compareByErfassungsgebietsart(one, another);

    if (comparedByErfassungsgebietsart == 0) {
      return compareByPosition(one, another);
    }

    return comparedByErfassungsgebietsart;
  }

  private int compareByErfassungsgebietsart(E one, E another) {
    boolean oneUrnenwahlgebiet = one.isUrnenwahlgebiet();
    boolean oneBriefwahlgebiet = one.isBriefwahlgebiet();
    boolean oneErfassungsgebiet = oneUrnenwahlgebiet || oneBriefwahlgebiet;

    boolean anotherUrnenwahlgebiet = another.isUrnenwahlgebiet();
    boolean anotherBriefwahlgebiet = another.isBriefwahlgebiet();
    boolean anotherErfassungsgebiet = anotherUrnenwahlgebiet || anotherBriefwahlgebiet;

    if (oneErfassungsgebiet && anotherErfassungsgebiet) {
      if (oneUrnenwahlgebiet) {
        if (anotherUrnenwahlgebiet) {
          return 0;
        }

        return -1;
      }

      if (anotherBriefwahlgebiet) {
        return 0;
      }

      return 1;
    }

    if (oneErfassungsgebiet) {
      return -1;
    }

    if (anotherErfassungsgebiet) {
      return 1;
    }

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

  private int compareByPosition(E one, E another) {
    return GEBIET_BY_POSITION_COMPARATOR.compare(one, another);
  }
}
