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

import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.inject.Inject;

import de.ivu.elect.business.exchange.entity.ImportUpdateReport;
import de.ivu.elect.business.gebietsbaum.control.Gebietsbaum;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietTK;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartTK;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.jee.exchange.ImportOptions;
import de.ivu.elect.jee.exchange.Violations;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.util.CollectionSeparator;

public class GebietsbaumImporterReportUtil {

  @Inject
  private transient Messages messages;

  @Inject
  private transient GebietsartDAO gebietsartDAO;

  public GebietsbaumImporterReportUtil() {
    super();
  }

  public void erstelleBericht(Mandant mandant, Gebietsbaum importObject, StringBuilder bericht) {
    erstelleBericht(mandant, importObject.getGebiete(), bericht, true);
  }

  public void erstelleBericht(Mandant mandant, List<Gebiet> gebieteExtern, StringBuilder bericht) {
    erstelleBericht(mandant, gebieteExtern, bericht, false);
  }

  private void erstelleBericht(Mandant mandant, List<Gebiet> gebieteExtern, StringBuilder bericht, boolean anzahlGebieteOhneNameIncluded) {
    // Bericht nach ELECT-15
    Map<GebietsartTK, Long> anzahlGebietePerGebietsartTk = new HashMap<>();
    Map<GebietsartTK, Gebietsart> gebietsartPerGebietsartTk = new HashMap<>();

    // ELECT-4051
    Map<GebietsartTK, Gebietsart> gebietsartenInDb = gebietsartDAO.findByAll(mandant).stream().collect(Collectors.toMap(Gebietsart::getGebietsartTK, Function.identity()));

    long anzahlGebieteOhneName = 0;
    long anzahlGebieteOhneKurztext = 0;

    for (Gebiet gebiet : gebieteExtern) {
      Gebietsart gebietsart = gebiet.getGebietsart();
      GebietsartTK gebietsartTk = gebietsart.getGebietsartTK();

      gebietsartPerGebietsartTk.put(gebietsartTk, gebietsart);

      Long anzahlGebiete = anzahlGebietePerGebietsartTk.get(gebietsartTk);

      if (anzahlGebiete == null) {
        anzahlGebiete = 0L;
      }

      anzahlGebiete++;
      anzahlGebietePerGebietsartTk.put(gebietsartTk, anzahlGebiete);

      if (isBlank(gebiet.getName())) {
        anzahlGebieteOhneName++;
      }

      if (isBlank(gebiet.getKuerzel())) {
        anzahlGebieteOhneKurztext++;
      }
    }

    bericht.append(getMessage("gebiet.import.gebiet.art.anzahl"));
    bericht.append("\n");

    for (Entry<GebietsartTK, Long> entry : anzahlGebietePerGebietsartTk.entrySet()) {
      // ELECT-4051
      if (gebietsartenInDb.containsKey(entry.getKey())) {
        Gebietsart gebietsartInDb = gebietsartenInDb.get(entry.getKey());

        bericht.append(defaultString(gebietsartInDb.getTitel(), gebietsartInDb.getName())); // ELECT-7510
      } else {
        bericht.append(entry.getKey().getName());
      }

      bericht.append(": ");
      bericht.append(entry.getValue());
      bericht.append("\n");
    }

    if (anzahlGebieteOhneNameIncluded) {
      bericht.append("\n");

      bericht.append(getMessage("gebiet.import.gebiet.anzahl.ohne.text"));
      bericht.append(": ");
      bericht.append(anzahlGebieteOhneName);
      bericht.append("\n");
      bericht.append(getMessage("gebiet.import.gebiet.anzahl.ohne.kurztext"));
      bericht.append(": ");
      bericht.append(anzahlGebieteOhneKurztext);
    }
  }

  public ImportUpdateReport createImportUpdateReport(List<Gebiet> gebieteInDb, Gebietsbaum importObject, Violations violations, ImportOptions importOptions, StringBuilder bericht) {
    return createImportUpdateReport(gebieteInDb, importObject.getGebiete(), violations, importOptions, bericht);
  }

  public ImportUpdateReport createImportUpdateReport(List<Gebiet> gebieteInDb, List<Gebiet> gebieteExtern, Violations violations, ImportOptions importOptions, StringBuilder bericht) {
    return createImportUpdateReport(gebieteInDb, gebieteExtern, GebietTK.getGebietToTKFunction(), violations, importOptions, bericht);
  }

  public ImportUpdateReport createImportUpdateReport(List<Gebiet> gebieteInDb, List<Gebiet> gebieteExtern, Function<Gebiet, GebietTK> gebietToTKFunction, Violations violations,
      ImportOptions importOptions, StringBuilder bericht) {
    CollectionSeparator<Gebiet, GebietTK> collectionSeparator = new CollectionSeparator<>(gebieteExtern, gebieteInDb, gebietToTKFunction);

    return new ImportUpdateReport(violations, collectionSeparator.getInFirstNotInSecond().size(), collectionSeparator.getInSecondNotInFirst().size(), collectionSeparator.getInBoth().size(),
        importOptions, bericht);
  }

  protected String getMessage(String msgKey, Object... params) {
    return messages.getMessageForMessageKey(msgKey, params);
  }
}
