package de.ivu.elect.exchange.gebietsbaum;

import java.io.InputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Nullable;
import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.datei.entity.Datei;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.control.ImportExportStreamCreator;
import de.ivu.elect.business.gebietsbaum.boundary.GebietsartDAO;
import de.ivu.elect.business.gebietsbaum.entity.AbstractGebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietGeometrieImportContext;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartConstants;
import de.ivu.elect.core.exchange.gebietsbaum.AbstractEsriGebietGeometrieImportMapper;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaStringSelectOneProperty;
import de.ivu.elect.presentation.LambdaEntitySelectOneMenuProperty;
import de.ivu.elect.presentation.gebietsbaum.shp.ShpFileConfig;

public class SimpleGebietGeometrieImportMapper extends AbstractEsriGebietGeometrieImportMapper {

  private static final Logger LOG = LoggerFactory.getLogger(SimpleGebietGeometrieImportMapper.class);

  public static final String GEBIET_GEOMETRIE_IMPORT_FILE_FORMAT = "gebiet.geometrie.import.file.format.simple";

  private static final String GEBIETSART_KEY = "GEBIETSART_KEY";

  private static final String SPALTE_KEY = "SPALTE_KEY";

  @Inject
  private transient GebietsartDAO gebietsartDAO;

  @Inject
  private transient Messages messages;

  @Inject
  private transient ImportExportStreamCreator importExportStreamCreator;

  @Inject

  @Override
  public FileFormat getFileFormat() {
    return new FileFormat(GEBIET_GEOMETRIE_IMPORT_FILE_FORMAT, FileType.ZIP);
  }

  @Override
  public void addProperties(FormBuilder formBuilder, GebietGeometrieImportContext context, @Nullable Datei datei) {

    List<Gebietsart> gebietsarten = findeGebietsarten(context);
    if (gebietsarten.isEmpty()) {
      return;
    }

    gebietsarten.sort(Comparator.comparing(Gebietsart::getTitelWennLeerName));

    formBuilder.addProperty(new LambdaEntitySelectOneMenuProperty<>(gebietsarten, x -> context.put(GEBIETSART_KEY, x),
        () -> context.get(GEBIETSART_KEY, Gebietsart.class), AbstractGebietsart::getTitelWennLeerName, GebietsartConstants.MESSAGE_KEY_ENTITY_EINZAHL, true,
        true));

    List<String> spalten = findeSpalten(datei);

    formBuilder.addProperty(new LambdaStringSelectOneProperty(messages.getMessageForMessageKey("gebiet.geometrie.import.file.format.simple.spalte"), true,
        s -> context.put(SPALTE_KEY, s), () -> context.get(SPALTE_KEY, String.class), spalten, true));

  }

  private List<String> findeSpalten(Datei datei) {

    if (datei == null) {
      return Collections.emptyList();
    }

    Set<String> result = new HashSet<>();
    try {

      try (InputStream is = datei.createInputStream(importExportStreamCreator)) {

        tryRun(is, new ShpFileConfig() {
          @Nullable
          @Override
          public String getGebietsartFuerShpUndDBFEintrag(String shpId, String filename, Map<String, String> entriesNachSpaltenname, Map<Integer, String> entriesNachSpaltenidex) {
            return null;
          }

          @Nullable
          @Override
          public String getNummerFuerDBFEintrag(String shpId, String filename, Map<String, String> entriesNachSpaltenname, Map<Integer, String> entriesNachSpaltenindex) {
            result.addAll(entriesNachSpaltenname.keySet());
            return null;
          }

          @Override
          public boolean isReturnGebieteOhneNummer() {
            return false;
          }

          @Override
          public boolean isReturnGebieteOhneGebietsart() {
            return false;
          }
        });
      }

    } catch (Exception e) {
      LOG.warn("Fehler beim Lesen der Datei: " + e.getMessage(), e);
      return Collections.emptyList();
    }

    return result.stream().sorted().collect(Collectors.toList());

  }

  private List<Gebietsart> findeGebietsarten(GebietGeometrieImportContext context) {

    if (context.getWahl() != null) {
      return gebietsartDAO.findByWahlart(context.getWahl().getWahlart());
    }

    if (context.getWahltermin() != null) {
      return gebietsartDAO.findByAll(context.getWahltermin().getMandant());
    }
    return Collections.emptyList();
  }

  @Override
  protected ShpFileConfig createConfig(GebietGeometrieImportContext gebietGeometrieImportContext) {
    return new ShpFileConfig() {

      @Nullable
      @Override
      public String getGebietsartFuerShpUndDBFEintrag(String shpId, String filename, Map<String, String> entriesNachSpaltenname, Map<Integer, String> entriesNachSpaltenidex) {
        Gebietsart gebietsart = gebietGeometrieImportContext.get(GEBIETSART_KEY, Gebietsart.class);
        if (gebietsart == null) {
          return null;
        }
        return gebietsart.getName();
      }

      @Nullable
      @Override
      public String getNummerFuerDBFEintrag(String shpId, String filename, Map<String, String> entriesNachSpaltenname, Map<Integer, String> entriesNachSpaltenindex) {
        String spaltenName = gebietGeometrieImportContext.get(SPALTE_KEY, String.class);
        if (StringUtils.isBlank(spaltenName)) {
          return null;
        }

        return entriesNachSpaltenname.get(spaltenName);
      }

      @Override
      public boolean isReturnGebieteOhneNummer() {
        return false;
      }

      @Override
      public boolean isReturnGebieteOhneGebietsart() {
        return false;
      }
    };
  }

}
