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

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import javax.ejb.Stateless;
import javax.inject.Inject;

import de.ivu.elect.business.datei.entity.DateiImportBerichtCustomData;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungCreate;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungExchangeContext;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungImportAttacher;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungImportExchange;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungsartImportTKFactory;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigung;
import de.ivu.elect.business.entschaedigung.entity.EntschaedigungMeta;
import de.ivu.elect.business.entschaedigung.entity.EntschaedigungTK;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigungsart;
import de.ivu.elect.business.exchange.control.AbstractEntityImporter;
import de.ivu.elect.business.exchange.control.ImportExchange;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.entity.Meta;
import de.ivu.elect.jee.entity.tk.EntityTK;
import de.ivu.elect.jee.exchange.ImportOptions;
import de.ivu.elect.jee.exchange.Violations;

@Stateless
public class EntschaedigungImporter extends
    AbstractEntityImporter<Entschaedigung, EntschaedigungTK, EntschaedigungExchangeContext, DateiImportBerichtCustomData>
{

  @Inject
  private EntschaedigungDAO entschaedigungDAO;

  @Inject
  private EntschaedigungMeta entschaedigungMeta;

  @Inject
  private EntschaedigungCreate entschaedigungCreate;

  @Inject
  private EntschaedigungImportExchange entschaedigungImportExchange;

  @Inject
  private EntschaedigungImportAttacher entschaedigungImportAttacher;

  @Inject
  private EntschaedigungsartDAO entschaedigungsartDAO;

  // HINT: Überschreiben, um Sichtbarkeit zu ändern
  @Override
  public void importiereImportObject(List<Entschaedigung> inDatei,
      EntschaedigungExchangeContext entschaedigungExchangeContext, ImportOptions importOptions,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    super.importiereImportObject(inDatei, entschaedigungExchangeContext, importOptions, dateiImportBerichtCustomData,
        bericht);
  }

  @Override
  protected void persistiere(Collection<Entschaedigung> inDateiCollection, EntschaedigungExchangeContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {

    Map<EntityTK, Entschaedigungsart> entschaedigungsartMap = createEntschaedigungsartMap(context.getWahltermin());

    for (Entschaedigung inDatei : inDateiCollection) {

      if (inDatei.getEntschaedigungsart() != null) {
        attachEntschaedigungsart(inDatei, entschaedigungsartMap);
      }
      if (inDatei.getPersonendaten() != null) {
        entschaedigungImportAttacher.attachPersonendaten(inDatei, context);
      }
      if (inDatei.getAuszahlung() != null) {
        entschaedigungImportAttacher.attachAuszahlung(inDatei, context);
      }

      entschaedigungCreate.save(inDatei);
    }

  }

  private void attachEntschaedigungsart(Entschaedigung inDatei,
      Map<EntityTK, Entschaedigungsart> entschaedigungsartMap) {
    Entschaedigungsart entschaedigungsartInDb = entschaedigungsartMap
        .get(EntschaedigungsartImportTKFactory.create(inDatei.getEntschaedigungsart()));
    inDatei.setEntschaedigungsart(entschaedigungsartInDb);
  }

  private Map<EntityTK, Entschaedigungsart> createEntschaedigungsartMap(Wahltermin wahltermin) {
    Map<EntityTK, Entschaedigungsart> result = new HashMap<>();

    for (Entschaedigungsart entity : entschaedigungsartDAO.findByWahltermin(wahltermin)) {
      result.put(EntschaedigungsartImportTKFactory.create(entity), entity);
    }

    return result;
  }

  @Override
  protected void aktualisiere(Entschaedigung inDatei, Entschaedigung inDb,
      EntschaedigungExchangeContext entschaedigungExchangeContext,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {

    inDatei.copyEntityAttributesUsingSetter(inDb);

  }

  @Override
  protected void loescheAusDatenbank(Collection<Entschaedigung> entitiesInDb,
      EntschaedigungExchangeContext entschaedigungExchangeContext,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void validiere(Violations violations, List<Entschaedigung> entschaedigungs,
      EntschaedigungExchangeContext entschaedigungExchangeContext, ImportOptions importOptions) {
    entschaedigungs.forEach(this::validateEntity);
  }

  @Override
  public void erstelleBericht(List<Entschaedigung> entschaedigungs,
      EntschaedigungExchangeContext entschaedigungExchangeContext, ImportOptions importOptions, StringBuilder bericht,
      boolean vorab) {
    // nothing to do
  }

  @Override
  protected List<Entschaedigung> getAllEntitiesInDB(EntschaedigungExchangeContext entschaedigungExchangeContext) {
    return entschaedigungDAO.findByWahltermin(entschaedigungExchangeContext.getWahltermin());
  }

  @Override
  protected Function<Entschaedigung, EntschaedigungTK> getEntityToEntityTKFunction() {
    return Entschaedigung::getEntschaedigungTK;
  }

  @Override
  protected ImportExchange<List<Entschaedigung>, EntschaedigungExchangeContext> getExchange() {
    return entschaedigungImportExchange;
  }

  @Override
  protected Meta getMetaForEntityInternal() {
    return entschaedigungMeta;
  }
}
