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

import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.join;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.GruppeConstants;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPersonConstants;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPersonPoolSearchResultEntry;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPersonTyp;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.presentation.table.AbstractColumnEntry;

public class WahlvorschlagsPersonPoolSearchResultEntryWahlvorschlagsPersonTypPerGruppeColumn extends AbstractColumnEntry<WahlvorschlagsPersonPoolSearchResultEntry> {

  private static final long serialVersionUID = 1L;

  private static final int VALUES_FORMATTED_SUB_LIST_MAX_SIZE = 10;

  private List<String> valuesFormatted;

  private List<String> valuesFormattedSubList;

  private String valuesFormattedTooltip;

  public WahlvorschlagsPersonPoolSearchResultEntryWahlvorschlagsPersonTypPerGruppeColumn(Messages messages) {
    super(messages);
  }

  @Override
  public ColumnType getType() {
    return ColumnType.COLLECTION;
  }

  @Override
  public String getHeader() {
    return getMessage("wahlvorschlagsperson.pool.selection.search.result.gruppe.header", getMessage(GruppeConstants.MESSAGE_KEY_ENTITY_EINZAHL),
        getMessage(WahlvorschlagsPersonConstants.MESSAGE_KEY_WAHLVORSCHLAGS_PERSON_TYP_EINZAHL));
  }

  @Override
  public String getTooltip(WahlvorschlagsPersonPoolSearchResultEntry entry) {
    if (entry != null) {
      return getTooltip(entry.getGebietsinformationenPerWahlvorschlagsPersonTypPerGruppe());
    }

    return super.getTooltip(entry);
  }

  private String getTooltip(Map<Gruppe, Map<WahlvorschlagsPersonTyp, Collection<Gebiet>>> gebietePerWahlvorschlagsPersonTypPerGruppe) {
    if (valuesFormattedTooltip == null) {
      valuesFormattedTooltip = join(getValuesFormatted(gebietePerWahlvorschlagsPersonTypPerGruppe), System.lineSeparator());
    }

    return valuesFormattedTooltip;
  }

  @Override
  public Object getValue(WahlvorschlagsPersonPoolSearchResultEntry entry) {
    if (entry != null) {
      return getValuesFormattedSubList(entry.getGebietsinformationenPerWahlvorschlagsPersonTypPerGruppe());
    }

    return new ArrayList<>();
  }

  private List<String> getValuesFormattedSubList(Map<Gruppe, Map<WahlvorschlagsPersonTyp, Collection<Gebiet>>> gebietePerWahlvorschlagsPersonTypPerGruppe) {
    if (valuesFormattedSubList == null) {

      // ELECT-10959  was soll dieser Code machen?
      List<String> valuesFormatted = getValuesFormatted(gebietePerWahlvorschlagsPersonTypPerGruppe);

      int valuesFormattedCount = valuesFormatted.size();

      valuesFormattedSubList = valuesFormatted.subList(0, Math.min(VALUES_FORMATTED_SUB_LIST_MAX_SIZE, valuesFormattedCount));

      int valuesSkippedCount = valuesFormattedCount - VALUES_FORMATTED_SUB_LIST_MAX_SIZE;

      if (valuesSkippedCount > 0) {
        valuesFormattedSubList.add(getMessage("wahlvorschlagsperson.pool.selection.search.result.gruppe.entries.skipped", valuesSkippedCount));
      }
    }

    return valuesFormattedSubList;
  }

  private List<String> getValuesFormatted(Map<Gruppe, Map<WahlvorschlagsPersonTyp, Collection<Gebiet>>> gebietePerWahlvorschlagsPersonTypPerGruppe) {
    if (valuesFormatted == null) {
      valuesFormatted = formatGebietePerWahlvorschlagsPersonTypPerGruppe(gebietePerWahlvorschlagsPersonTypPerGruppe);
    }

    return valuesFormatted;
  }

  private List<String> formatGebietePerWahlvorschlagsPersonTypPerGruppe(Map<Gruppe, Map<WahlvorschlagsPersonTyp, Collection<Gebiet>>> gebietePerWahlvorschlagsPersonTypPerGruppe) {
    List<String> result = new ArrayList<>();

    for (Entry<Gruppe, Map<WahlvorschlagsPersonTyp, Collection<Gebiet>>> entryPerGruppe : gebietePerWahlvorschlagsPersonTypPerGruppe.entrySet()) {
      Gruppe gruppe = entryPerGruppe.getKey();
      String gruppeFormatted = defaultIfBlank(gruppe.getKurzname(), gruppe.getName());

      for (Entry<WahlvorschlagsPersonTyp, Collection<Gebiet>> entryPerWahlvorschlagsPersonTyp : entryPerGruppe.getValue().entrySet()) {
        String wahlvorschlagsPersonTypFormatted = getMessage(entryPerWahlvorschlagsPersonTyp.getKey());

        List<String> gebieteFormatted = entryPerWahlvorschlagsPersonTyp.getValue().stream() //
            .map(gebiet -> defaultIfBlank(gebiet.getNummer(), gebiet.getName())).collect(toList());

        String msgKey = "wahlvorschlagsperson.pool.selection.search.result.gruppe.entry.format.per.gebiet";

        if (gebieteFormatted.size() > 1) {
          msgKey = "wahlvorschlagsperson.pool.selection.search.result.gruppe.entry.format.per.gebiete";
        }

        result.add(getMessage(msgKey, gruppeFormatted, wahlvorschlagsPersonTypFormatted, join(gebieteFormatted, ", ")));
      }
    }

    return result;
  }
}
