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

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

import de.ivu.elect.business.gebietsbaum.entity.EntityMitGebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;

public class GebietByBreadthFirstComparator implements Comparator<Gebiet>, Serializable {

  private static final long serialVersionUID = 1L;

  public static final GebietByBreadthFirstComparator INSTANCE = new GebietByBreadthFirstComparator();

  private static final Comparator<Gebiet> GEBIET_BY_NUMMER_COMPARATOR = GebietByNummerComparator.ASCENDING;

  public GebietByBreadthFirstComparator() {
    super();
  }

  public int compare(EntityMitGebiet one, EntityMitGebiet another) {
    return compare(one.getGebiet(), another.getGebiet());
  }

  @Override
  public int compare(Gebiet one, Gebiet another) {
    if (Objects.equals(one, another)) {
      return 0;
    }
    int result = compareDepth(one, another);

    if (result == 0) {
      result = compareParentPosition(one, another);
    }

    if (result == 0) {
      result = comparePosition(one, another);
    }

    if (result == 0) {
      result = compareNummer(one, another);
    }

    return result;
  }

  public static int compareNummer(Gebiet one, Gebiet another) {
    return GEBIET_BY_NUMMER_COMPARATOR.compare(one, another);

  }

  public static int comparePosition(Gebiet one, Gebiet another) {
    if (one.getPosition() == null || another.getPosition() == null) {
      if (one.getPosition() != null) {
        return -1;
      }

      if (another.getPosition() != null) {
        return 1;
      }

      return 0;
    }

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

  private int compareParentPosition(Gebiet one, Gebiet another) {
    int result = 0;

    if (one.getUebergeordnetesGebiet() != null && another.getUebergeordnetesGebiet() != null) {
      result = compareParentPosition(one.getUebergeordnetesGebiet(), another.getUebergeordnetesGebiet());
    }

    if (result == 0) {
      result = comparePosition(one, another);
    }

    return result;
  }

  protected int compareDepth(Gebiet one, Gebiet another) {
    return Long.compare(one.getTiefeImBaum(), another.getTiefeImBaum());
  }

}
