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

import java.util.Collection;
import java.util.List;
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.EntschaedigungsartExchangeContext;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungsartImportExchange;
import de.ivu.elect.business.entschaedigung.control.EntschaedigungsartImportTKFactory;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigungsart;
import de.ivu.elect.business.entschaedigung.entity.EntschaedigungsartMeta;
import de.ivu.elect.business.exchange.control.AbstractEntityImporter;
import de.ivu.elect.business.exchange.control.ImportExchange;
import de.ivu.elect.business.exchange.entity.ImportUpdateReport;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
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;
import de.ivu.elect.util.CollectionSeparator;

@Stateless
public class EntschaedigungsartImporter extends AbstractEntityImporter<Entschaedigungsart, EntityTK, EntschaedigungsartExchangeContext, DateiImportBerichtCustomData> {

  private static final String MSG_KEY_BEARBEITEN_NICHT_ERLAUBT = "entschaedigungsart.importer.bearbeiten.nicht.erlaubt.warning.message";

  @Inject
  private transient WahlDAO wahlDao;

  @Inject
  private transient WahlterminDAO wahlterminDao;

  @Inject
  private transient AuszahlungDAO auszahlungDAO;

  @Inject
  private transient EntschaedigungsartDAO entschaedigungsartDao;

  @Inject
  private transient EntschaedigungsartImportExchange entschaedigungsartImportExchange;

  @Inject
  private transient EntschaedigungsartMeta entschaedigungsartMeta;

  public EntschaedigungsartImporter() {
    super();
  }

  @Override
  protected ImportExchange<List<Entschaedigungsart>, EntschaedigungsartExchangeContext> getExchange() {
    return entschaedigungsartImportExchange;
  }

  @Override
  public Meta getMetaForEntityInternal() {
    return entschaedigungsartMeta;
  }

  @Override
  public void validiere(Violations violations, List<Entschaedigungsart> entschaedigungsarten, EntschaedigungsartExchangeContext context, ImportOptions importOptions) {
    entschaedigungsarten.forEach(entschaedigungsart -> validateEntity(violations, entschaedigungsart, entschaedigungsart.getEntschaedigungsartTK()));
  }

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

  @Override
  protected void persistiere(Collection<Entschaedigungsart> entschaedigungsartenNurInDateiNichtInDb, EntschaedigungsartExchangeContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    entschaedigungsartenNurInDateiNichtInDb.forEach(entschaedigungsart -> {
      if (context.hasWahl()) {
        Wahl wahl = wahlDao.attach(context.getWahl());

        entschaedigungsart.setWahl(wahl);
        entschaedigungsart.setWahltermin(wahl.getWahltermin());
      } else {
        entschaedigungsart.setWahltermin(wahlterminDao.attach(context.getWahltermin()));
      }

      entschaedigungsartDao.persist(entschaedigungsart);
    });
  }

  @Override
  protected void aktualisiere(Entschaedigungsart entschaedigungsartInDatei, Entschaedigungsart entschaedigungsartInDb, EntschaedigungsartExchangeContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {

    if (isBearbeitenNichtErlaubt(entschaedigungsartInDb)) {
      bericht.append(getMessage(MSG_KEY_BEARBEITEN_NICHT_ERLAUBT, entschaedigungsartInDb.getBezeichnung()));
    } else {
      entschaedigungsartInDatei.copyEntityAttributesUsingSetter(entschaedigungsartInDb);
    }
  }

  @Override
  protected ImportUpdateReport createImportUpdateReport(CollectionSeparator<Entschaedigungsart, EntityTK> separator, Violations violations,
      EntschaedigungsartExchangeContext entschaedigungsartExchangeContext, ImportOptions importOptions, StringBuilder bericht) {
    if (importOptions.isAktualisiereBestehendenDaten()) {
      for (EntityTK entschaedigungsartTK : separator.getInBoth()) {
        Entschaedigungsart entschaedigungsartInDb = separator.getSecondMap().get(entschaedigungsartTK);

        if (isBearbeitenNichtErlaubt(entschaedigungsartInDb)) {
          violations.addWarning(MSG_KEY_BEARBEITEN_NICHT_ERLAUBT, entschaedigungsartInDb.getBezeichnung());
        }
      }
    }

    return super.createImportUpdateReport(separator, violations, entschaedigungsartExchangeContext, importOptions, bericht);
  }

  @Override
  protected void loescheAusDatenbank(Collection<Entschaedigungsart> entschaedigungsartenInDb, EntschaedigungsartExchangeContext context, DateiImportBerichtCustomData dateiImportBerichtCustomData,
      StringBuilder bericht) {
    entschaedigungsartenInDb.forEach(entschaedigungsart -> entschaedigungsartDao.remove(entschaedigungsart));
  }

  @Override
  protected List<Entschaedigungsart> getAllEntitiesInDB(EntschaedigungsartExchangeContext context) {
    if (context.hasWahl()) {
      return entschaedigungsartDao.findByWahl(context.getWahl());
    }

    return entschaedigungsartDao.findByWahltermin(context.getWahltermin());
  }

  @Override
  protected Function<Entschaedigungsart, EntityTK> getEntityToEntityTKFunction() {
    return EntschaedigungsartImportTKFactory::create;
  }

  @Override
  public void erstelleBericht(List<Entschaedigungsart> importObject, EntschaedigungsartExchangeContext context, ImportOptions importOptions, StringBuilder bericht, boolean vorab) {
    // nichts zu tun
  }

  private boolean isBearbeitenNichtErlaubt(Entschaedigungsart entschaedigungsart) {
    return !entschaedigungsart.isBearbeitbar(auszahlungDAO);
  }
}
