
package de.ivu.elect.presentation.gruppe.table;

import static java.util.stream.Collectors.joining;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.NlGebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.kandidatur.boundary.AbstractListenkandidaturDAO;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahlrechtspruefung.boundary.AbstractWahlrechtspruefungDAO;
import de.ivu.elect.business.wahlvorschlag.boundary.AbstractListeDAO;
import de.ivu.elect.business.wahlvorschlag.entity.AbstractWahlvorschlag;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.NlListe;
import de.ivu.elect.business.wahlvorschlag.entity.NlListeStatus;
import de.ivu.elect.business.wahlvorschlag.entity.StelInformationen;
import de.ivu.elect.business.wahlvorschlag.entity.StelInformationenFormatter;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

public class NlGruppeWahlkreiseColumn extends AbstractGruppeColumn<Gruppe> {

  private static final long serialVersionUID = 1L;

  public static final Pattern COMPILE = Pattern.compile(" ", Pattern.LITERAL);

  public NlGruppeWahlkreiseColumn(Messages messages, AbstractListeDAO listeDAO, EntityAufStimmzettelDaten entityAufStimmzettelDaten,
                                  GebietNummerFormatter gebietNummerFormatter, AbstractWahlrechtspruefungDAO wahlrechtspruefungDAO,
                                  AbstractListenkandidaturDAO listenkandidaturDAO) {
    super("NlGruppeWahlkreiseColumn", messages, "gruppe.colum.wahlkreis", ColumnType.COLLECTION, gruppe -> {
      Map<Gebiet, Liste> listeNachGebiet = listeDAO.findByGruppe(gruppe).stream()
          .collect(Collectors.toMap(AbstractWahlvorschlag::getGebiet, liste -> liste, (a, b) -> b));

      Function<List<Gebiet>, String> formatterWahlgebiete = wahlgebiete -> formatWahlgebiete(wahlgebiete, listeNachGebiet, gebietNummerFormatter,
          wahlrechtspruefungDAO, messages);

      BiFunction<StelInformationen, List<Gebiet>, String> formatterEinzelliste = (stelInformationen, wahlgebiete) -> formatterWahlgebiete.apply(wahlgebiete);

      BiFunction<StelInformationen, List<Gebiet>, String> formatterIdentischeListe = (stelInformationen, wahlgebiete) -> formatterWahlgebiete
          .apply(wahlgebiete);

      BiFunction<StelInformationen, List<Gebiet>, String> formatterListengruppe = (stelInformationen, wahlgebiete) -> {
        // ELECTVAPP-1041
        String mgsKey = "stel.nummer";
        if (stelInformationen.isUnechterStel()) {
          mgsKey = "stel.nummer.unecht";
        }
        return (COMPILE.matcher(messages.getMessageForMessageKey(mgsKey, stelInformationen.getStelNummerAnzeige())).replaceAll(Matcher.quoteReplacement("\u00A0")) + " " + formatterWahlgebiete.apply(wahlgebiete));
      };

      return new StelInformationenFormatter(entityAufStimmzettelDaten, listenkandidaturDAO)
          .formatGruppeStelWahlgebietePerStel(listeDAO.findByGruppe(gruppe), formatterEinzelliste, formatterIdentischeListe,
              formatterListengruppe);
    });
  }

  public static String formatWahlgebiete(List<Gebiet> wahlgebiete, Map<Gebiet, Liste> listeNachGebiet, GebietNummerFormatter gebietNummerFormatter,
                                         AbstractWahlrechtspruefungDAO wahlrechtspruefungDAO, Messages messages) {
    List<String> result = new ArrayList<>();
    for (Gebiet gebiet : wahlgebiete) {
      Liste liste = listeNachGebiet.get(gebiet);
      if (liste != null) {
        NlListeStatus nlListeStatus = NlListe.getNlListeStatus(liste, wahlrechtspruefungDAO);
        String text = messages.getMessageForMessageKey(nlListeStatus.getIconMsgKey()) + " " + gebietNummerFormatter.getDarstellung(gebiet);
        result.add(NlGruppeWahlkreiseColumn.COMPILE.matcher(text).replaceAll(Matcher.quoteReplacement("\u00A0")));
      }
    }
    return String.join(", ", result);
  }
}
