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

import de.ivu.elect.business.gebietsbaum.entity.DefaultGebietsart;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartBezirksart;

import javax.enterprise.inject.Specializes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ELECT-8717
 */
@Specializes
public class CoreGebietsbaumImportFilter extends GebietsbaumImportFilter {


  @Override
  public Gebietsbaum filter(Gebietsbaum gebietsbaum) {
    Gebietsbaum filter = super.filter(gebietsbaum);
    return ersetzeReservezirk(filter);
  }

  private Gebietsbaum ersetzeReservezirk(Gebietsbaum gebietsbaum) {

    if (isReservebezirkVorhanden(gebietsbaum)) {
      return new Gebietsbaum(gebietsbaum.getWahl(), filterReserverbezirke(gebietsbaum.getGebiete()), filterReserveBezirksarten(gebietsbaum.getGebietsarten()));
    }
    return gebietsbaum;
  }

  private List<Gebietsart> filterReserveBezirksarten(List<Gebietsart> gebietsarten) {

    if (gebietsarten == null) {
      return Collections.emptyList();
    }
    return gebietsarten.stream().filter(g -> !isReservebezirk(g)).collect(Collectors.toList());
  }

  private List<Gebiet> filterReserverbezirke(List<Gebiet> gebiete) {
    if (gebiete == null) {
      return Collections.emptyList();
    }

    List<Gebiet> result = new ArrayList<>();
    for (Gebiet gebiet : gebiete) {
      if (isReservebezirk(gebiet)) {
        gebiet.setUebergeordnetesGebiet(null); // aus Baum entfernen
      } else {
        result.add(gebiet);
      }
    }

    return result;
  }

  private boolean isReservebezirkVorhanden(Gebietsbaum gebietsbaum) {
    if (gebietsbaum.getGebiete() != null) {
      for (Gebiet gebiet : gebietsbaum.getGebiete()) {
        if (isReservebezirk(gebiet)) {
          return true;
        }
      }
    }
    if (gebietsbaum.getGebietsarten() != null) {
      for (Gebietsart gebietsart : gebietsbaum.getGebietsarten()) {
        if (isReservebezirk(gebietsart)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean isReservebezirk(Gebietsart gebietsart) {
    return gebietsart != null && (GebietsartBezirksart.RESERVEBEZIRK.name().equalsIgnoreCase(gebietsart.getName()) || DefaultGebietsart.RESERVERBEZIRK.equalsGebietsart(gebietsart));
  }

  private boolean isReservebezirk(Gebiet gebiet) {
    return gebiet != null && isReservebezirk(gebiet.getGebietsart());
  }
}
