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

import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import de.ivu.elect.business.gebietsbaum.boundary.AbstractGebietDAO;
import de.ivu.elect.business.wahl.boundary.AbstractWahlDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahllokalsystem.boundary.AbstractWahllokalsystemStatusDAO;
import de.ivu.elect.business.wahllokalsystem.entity.WahllokalsystemStatus;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.faces.UserLocale;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.presentation.table.DefaultColumnEntry;

public class WahllokalsystemStatusDokumenteColumn extends DefaultColumnEntry<WahllokalsystemStatus> {

  private static final long serialVersionUID = 1L;

  private final UserLocale userLocale;

  private final Wahl wahlNotAttached;

  private final AbstractWahllokalsystemStatusDAO wahllokalsystemStatusDAO;

  private final AbstractGebietDAO abstractGebietDAO;

  private final AbstractWahlDAO abstractWahlDAO;

  public WahllokalsystemStatusDokumenteColumn(Messages messages, UserLocale userLocale, Wahl wahl, AbstractWahllokalsystemStatusDAO wahllokalsystemStatusDAO, AbstractGebietDAO abstractGebietDAO, AbstractWahlDAO abstractWahlDAO) {
    super("WahllokalsystemStatus-Dokumente" + getWahlId(wahl), messages, "wahllokalsystem.status.dokumente.column", ColumnType.STRING, null,
        new Object[]{getWahlname(wahl)});
    this.userLocale = userLocale;
    this.wahlNotAttached = wahl;
    this.wahllokalsystemStatusDAO = wahllokalsystemStatusDAO;
    this.abstractGebietDAO = abstractGebietDAO;
    this.abstractWahlDAO = abstractWahlDAO;
  }



  @Override
  public Object getValue(WahllokalsystemStatus entityOhneWahl) {
    WahllokalsystemStatus entityFuerWahl = getEntityFuerWahl(entityOhneWahl);
    if (entityFuerWahl == null) {
      return null;
    }

    return entityFuerWahl.getZeitpunktDokumente().keySet().stream()
        .map(dateSupplier -> erfuelltZeichen(dateSupplier.get()))
        .collect(Collectors.joining());
  }

  @Override
  public String getTooltip(WahllokalsystemStatus entityOhneWahl) {
    WahllokalsystemStatus entityFuerWahl = getEntityFuerWahl(entityOhneWahl);
    if (entityFuerWahl == null) {
      return null;
    }
    return entityFuerWahl.getZeitpunktDokumente().entrySet().stream()
        .map(e -> getMessage(e.getValue()) + "\u00A0" + formatiereDatum(e.getKey().get()))
        .collect(Collectors.joining(", "));
  }

  private String erfuelltZeichen(Date zeitpunkt) {
    return getErfuelltZeichen(isErfuellt(zeitpunkt), getMessages());
  }

  public static String getErfuelltZeichen(boolean b, Messages messages) {
    if (b) {
      return messages.getMessageForMessageKey("wahllokalsystem.status.dokumente.erfuellt");
    }
    return messages.getMessageForMessageKey("wahllokalsystem.status.dokumente.nicht.erfuellt");
  }

  public static boolean isErfuellt(Date zeitpunkt) {
    return zeitpunkt != null;
  }

  @Nullable
  private WahllokalsystemStatus getEntityFuerWahl(WahllokalsystemStatus wahllokalsystemStatusNotAttached) {
    if (wahllokalsystemStatusNotAttached == null || wahlNotAttached == null) {
      return null;
    }
    WahllokalsystemStatus wahllokalsystemStatus = wahllokalsystemStatusDAO.attach(wahllokalsystemStatusNotAttached);
    Wahl wahl = abstractWahlDAO.attach(wahlNotAttached);
    if (wahl.equals(wahllokalsystemStatus.getGebiet().getWahl())) {
      return wahllokalsystemStatus;
    }

    return wahllokalsystemStatus.getWahllokalsystemStatusAndereWahl(wahl, wahllokalsystemStatusDAO, abstractGebietDAO);
  }

  private String formatiereDatum(Date date) {
    String result = erfuelltZeichen(date);
    if (isErfuellt(date)) {
      result += "\u00A0(" + userLocale.formatDateTime(date).replace(' ', '\u00A0') + ")";
    }

    return result;
  }

  public static String getWahlname(Wahl wahl) {
    if (wahl == null) {
      return "";
    }
    return wahl.getWahlart().getWahlartName();
  }

  public static String getWahlId(Wahl wahl) {
    if (wahl==null) {
      return null;
    }
    return wahl.getId().toString();
  }


}
