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

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.ergebnis.boundary.ErgebnisExtendedDAO;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.praesentation.entity.PraesentationBereitstellen;
import de.ivu.elect.business.praesentation.entity.PraesentationStatistikEntry;
import de.ivu.elect.business.praesentation.entity.PraesentationStatistikSearchResult;
import de.ivu.elect.business.praesentation.entity.PraesentationUploadServiceStatus;
import de.ivu.elect.business.praesentation.entity.PraesentationUploadServiceTyp;
import de.ivu.elect.business.wahl.entity.WahlParameterExtendedLoader;
import de.ivu.elect.jee.presentation.dynamictable.AbstractColumnBuilder;
import de.ivu.elect.jee.presentation.dynamictable.ColumnEntry;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.presentation.mandant.MandantSessionSelect;
import de.ivu.elect.presentation.table.DefaultColumnEntry;


import static de.ivu.elect.business.wahl.entity.WahlParameterWerte.PREASENTATIION_STATUS;
import static de.ivu.elect.business.wahl.entity.WahlParameterWerte.PREASENTATIION_UPLOAD_SERVICE_STATUS;
import static de.ivu.elect.business.wahl.entity.WahlParameterWerte.PREASENTATIION_UPLOAD_SERVICE_TYP;

@Named(PraesentationStatistikColumnBuilder.COMPONENT_NAME)
public class PraesentationStatistikColumnBuilder extends AbstractColumnBuilder<PraesentationStatistikSearchResult> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "praesentationStatistikColumnBuilder";

  @Inject
  private transient MandantSessionSelect mandantSessionSelect;

  @Inject
  private ErgebnisExtendedDAO ergebnisExtendedDAO;

  @Inject
  private transient WahlParameterExtendedLoader wahlParameterExtendedLoader;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> mandantNummerColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> mandantNameColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> wahlDatumColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> wahlNameColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> wahlArtColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> ergebnisArtColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> ergebnisZeitpunktColumn;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> generierungTyp;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> generierungZeitstempel;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> generierungDauer;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> uploadTyp;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> uploadStatus;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> uploadZeitstempel;

  private DefaultColumnEntry<PraesentationStatistikSearchResult> uploadDauer;

  @Override
  protected void initColumns() {
    if (isNurSystemMandant()) {
      mandantNummerColumn = new DefaultColumnEntry<>("mandantNummerColumn", messages, "praesentation.statistik.search.mandant.nummer", ColumnType.LONG,
          s -> ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getMandant().getNummer());
      mandantNameColumn = new DefaultColumnEntry<>("mandantNameColumn", messages, "praesentation.statistik.search.mandant.name", ColumnType.STRING,
          s -> ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getMandant().getName());
    }
    wahlDatumColumn = new DefaultColumnEntry<>("wahldatumColumn", messages, "praesentation.statistik.search.wahldatum", ColumnType.DATE,
        s -> ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getWahl().getWahldatum());
    wahlArtColumn = new DefaultColumnEntry<>("wahlArtColumn", messages, "praesentation.statistik.search.wahlart", ColumnType.STRING,
        s -> ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getWahl().getWahlart().getName());
    wahlNameColumn = new DefaultColumnEntry<>("wahlNameColumn", messages, "praesentation.statistik.search.wahlname", ColumnType.STRING,
        s -> ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getWahl().getName());
    ergebnisArtColumn = new DefaultColumnEntry<>("ergebnisArtColumn", messages, "praesentation.statistik.search.ergebnisart", ColumnType.STRING,
        s -> messages.lokalisiere(ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getErgebnisart()));

    ergebnisZeitpunktColumn = new DefaultColumnEntry<>("ergebnisZeitpunktColumn", messages, "praesentation.statistik.search.ergebniszeitpunkt",
        ColumnType.TIMESTAMP,
        s -> ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getZeitstempel());

    generierungTyp = new DefaultColumnEntry<>("generierungTyp", messages, "praesentation.statistik.search.generierungTyp", ColumnType.STRING,
        s -> messages.lokalisiere(wahlParameterExtendedLoader.resolveEnumValue(ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getWahl(),
            PREASENTATIION_STATUS,
            PraesentationBereitstellen.class)));

    generierungZeitstempel = new PraesentationStatistikGenerierungZeitstempelColumn("generierungZeitstempel", messages,
        "praesentation.statistik.search.generierungZeitstempel",
        ColumnType.TIMESTAMP,
        s -> findeLetztenEintrag(s.getStatistikEntries()).getZeitpunkt());

    generierungZeitstempel.setTooltipFct(s -> {
      if (findeLetztenEintrag(s.getStatistikEntries()).isError()) {
        return getMessage("praesentation.statistik.search.generierungError");
      }
      return "";
    });

    generierungDauer = new DefaultColumnEntry<>("generierungDauer", messages, "praesentation.statistik.search.generierungDauer",
        ColumnType.LONG,
        s -> findeLetztenEintrag(s.getStatistikEntries()).getDauerInMs());

    uploadTyp = new DefaultColumnEntry<>("uploadTyp", messages, "praesentation.statistik.search.uploadTyp", ColumnType.STRING,
        s -> messages.lokalisiere(wahlParameterExtendedLoader.resolveEnumValue(ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getWahl(),
            PREASENTATIION_UPLOAD_SERVICE_TYP,
            PraesentationUploadServiceTyp.class)));

    uploadStatus = new DefaultColumnEntry<>("uploadStatus", messages, "praesentation.statistik.search.uploadStatus", ColumnType.STRING,
        s -> messages.lokalisiere(wahlParameterExtendedLoader.resolveEnumValue(ergebnisExtendedDAO.findByPrimaryKey(s.getErgebnisPK()).getWahl(),
            PREASENTATIION_UPLOAD_SERVICE_STATUS,
            PraesentationUploadServiceStatus.class)));

    uploadZeitstempel = new PraesentationStatistikUploadZeitstempelColumn("uploadZeitstempel", messages,
        "praesentation.statistik.search.uploadZeitstempel", ColumnType.TIMESTAMP,
        s -> s.getPraesentationUploadEntry().getZeitpunkt());

    uploadZeitstempel.setTooltipFct(s -> {
      if (s.getPraesentationUploadEntry().isError()) {
        return getMessage("praesentation.statistik.search.uploadError");
      }
      return "";
    });

    uploadDauer = new DefaultColumnEntry<>("uploadDauer", messages, "praesentation.statistik.search.uploadDauer", ColumnType.LONG,
        s -> s.getPraesentationUploadEntry().getDauerInMs());

  }

  protected static PraesentationStatistikEntry findeLetztenEintrag(List<PraesentationStatistikEntry> statistikEntries) {
    return statistikEntries.stream().max(Comparator.comparing(PraesentationStatistikEntry::getZeitpunkt))
        .orElse(new PraesentationStatistikEntry(null, 0, 0, 0, 0, 0, 0, 0, false));
  }

  @Override
  protected List<ColumnEntry<? super PraesentationStatistikSearchResult>> getColumnEntriesSorted() {
    List<ColumnEntry<? super PraesentationStatistikSearchResult>> result = new ArrayList<>();
    if (isNurSystemMandant()) {
      result.add(mandantNummerColumn);
      result.add(mandantNameColumn);
    }
    result.add(wahlDatumColumn);
    result.add(wahlArtColumn);
    result.add(wahlNameColumn);
    result.add(ergebnisArtColumn);
    result.add(ergebnisZeitpunktColumn);
    result.add(generierungTyp);
    result.add(generierungZeitstempel);
    result.add(generierungDauer);
    result.add(uploadTyp);
    result.add(uploadStatus);
    result.add(uploadZeitstempel);
    result.add(uploadDauer);

    return result;
  }

  private boolean isNurSystemMandant() {
    return getMandant().getMandant().getArt().isSystemMandant() && !getMandant().getMandant().getArt().isCustomerMandant();
  }

  private Mandant getMandant() {
    return mandantSessionSelect.getMandant();
  }

}
