package de.ivu.elect.presentation.gebietsbaum;

import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.enterprise.inject.Specializes;
import javax.inject.Inject;
import javax.persistence.NoResultException;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietUK;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartUK;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.presentation.GebietCreateViewInit;

@Specializes
public class WasGebietCreateViewInit extends GebietCreateViewInit {

  public static final int MAXIMALE_LAENGE_BEZIRKNUMMER = 3;

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient Messages messages;

  @Override
  public void init(Gebiet gebiet) {
    super.init(gebiet);
    Gebietsart gebietsart = gebiet.getGebietsart();
    // ELECT-8124
    Wahl wahl = getSelectedWahl();
    if (wahl != null && wahl.getBerichtetAn() != null && gebietsart != null && (gebietsart.getBezirksart()
        .isBriefwahlbezirk() || gebietsart.getBezirksart()
        .isStimmbezirk()) && gebiet.getUebergeordnetesGebiet() != null) {

      Gebiet uebergeordnetesGebiet = gebiet.getUebergeordnetesGebiet();
      String nummerUebergeordnetString = uebergeordnetesGebiet.getNummer();

      long bezirkNummer = 0;

      Set<String> vorhandeneBezirksnummern = gebietExtendedDAO.findByWahlAndGebietsart(wahl, gebietsart).stream().map(g -> g.getNummerBezirk())
          .filter(Objects::nonNull).collect(Collectors.toSet());

      while (bezirkNummer < 1000) {
        bezirkNummer++;
        if (!vorhandeneBezirksnummern.contains(Long.toString(bezirkNummer))) {
          String neueNummer = nummerUebergeordnetString + StringUtils.leftPad(Long.toString(bezirkNummer), MAXIMALE_LAENGE_BEZIRKNUMMER, "0");

          // eigene Wahl
          try {
            if (gebietExtendedDAO.findByUK(new GebietUK(neueNummer, gebietsart.getGebietsartUK(), uebergeordnetesGebiet.getWahl().getWahlUK(),
                uebergeordnetesGebiet.getWahl().getWahltermin().getWahlterminUK())) != null) {
              continue;
            }
          } catch (NoResultException nre) {
            // alles gut
          }

          // Wahl an die berichtet wird
          try {
            Wahl berichtetAnWahl = wahl.getBerichtetAn();
            if (gebietExtendedDAO.findByUK(new GebietUK(neueNummer, new GebietsartUK(gebietsart.getName(), berichtetAnWahl.getMandant().getMandantUK()),
                berichtetAnWahl.getWahlUK(),
                berichtetAnWahl.getWahltermin().getWahlterminUK())) != null) {
              continue;
            }
          } catch (NoResultException nre) {
            // alles gut
          }

          setzeNummernUndName(gebiet, gebietsart, bezirkNummer, neueNummer);
          break;
        }
      }
    }
  }

  protected void setzeNummernUndName(Gebiet gebiet, Gebietsart gebietsart, long bezirkNummer, String neueNummer) {
    gebiet.setNummer(neueNummer);
    gebiet.setNummerBezirk(Long.toString(bezirkNummer));

    String name = null;
    if (gebietsart.getBezirksart().isStimmbezirk()) {
      name = messages.getMessageForMessageKey("gebiet.create.default.name.stimmbezirk", bezirkNummer);
    } else if (gebietsart.getBezirksart().isBriefwahlbezirk()) {
      name = messages.getMessageForMessageKey("gebiet.create.default.name.briefwahlbezirk", bezirkNummer);
    }
    gebiet.setName(name);
  }
}