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

import java.util.ArrayList;
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 org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.datei.entity.DateiImportBerichtCustomData;
import de.ivu.elect.business.exchange.control.AbstractEntityImporter;
import de.ivu.elect.business.exchange.control.ImportExchange;
import de.ivu.elect.jee.exchange.Violations;
import de.ivu.elect.business.staat.control.StaatenGruppeImportExchange;
import de.ivu.elect.business.staat.control.StaatenGruppeImportContext;
import de.ivu.elect.business.staat.entity.Staat;
import de.ivu.elect.business.staat.entity.StaatenGruppe;
import de.ivu.elect.business.staat.entity.StaatenGruppeMeta;
import de.ivu.elect.business.staat.entity.StaatenGruppeUK;
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.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.entity.Meta;
import de.ivu.elect.jee.exchange.ImportOptions;

@Stateless
public class StaatenGruppeImporter
    extends
      AbstractEntityImporter<StaatenGruppe, StaatenGruppeUK, StaatenGruppeImportContext, DateiImportBerichtCustomData> {

  @Inject
  private StaatenGruppeImportExchange importExchange;

  @Inject
  private StaatenGruppeMeta meta;

  @Inject
  private StaatenGruppeDAO staatenGruppeDAO;

  @Inject
  private StaatDAO staatDAO;

  @Inject
  private WahlDAO wahlDAO;

  @Inject
  private WahlterminDAO wahlterminDAO;

  public StaatenGruppeImporter() {
    super();
  }

  @Override
  protected ImportExchange<List<StaatenGruppe>, StaatenGruppeImportContext> getExchange() {
    return importExchange;
  }

  @Override
  protected void validiere(Violations violations, List<StaatenGruppe> entities, StaatenGruppeImportContext context, ImportOptions importOptions) {
    for (StaatenGruppe entity : entities) {
      validateEntity(violations, entity, entity.getStaatenGruppeTK());
    }
  }

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

  @Override
  protected void persistiere(Collection<StaatenGruppe> nurInDateiNichtInDatenbank, StaatenGruppeImportContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    Wahl wahl = wahlDAO.attach(context.getWahl());
    Wahltermin wahltermin = wahlterminDAO.attach(context.getWahltermin());

    Map<String, Staat> persistenteStaatenNachIsoCode = mappeStaatenNachIso3166Alpha2();

    for (StaatenGruppe staatenGruppe : nurInDateiNichtInDatenbank) {
      staatenGruppe.setWahltermin(wahltermin);
      staatenGruppe.setWahl(wahl);

      List<Staat> persistenteStaaten = new ArrayList<>();

      for (Staat staat : staatenGruppe.getStaats()) {
        if (!StringUtils.isBlank(staat.getIso3166Alpha2()) && persistenteStaatenNachIsoCode.containsKey(staat.getIso3166Alpha2())) {
          persistenteStaaten.add(persistenteStaatenNachIsoCode.get(staat.getIso3166Alpha2()));
        }
      }
      staatenGruppe.removeAllStaats();
      for (Staat persistenterStaat : persistenteStaaten) {
        staatenGruppe.addStaat(persistenterStaat);
      }
      staatenGruppeDAO.persist(staatenGruppe);
    }
  }

  private Map<String, Staat> mappeStaatenNachIso3166Alpha2() {

    Map<String, Staat> result = new HashMap<>();

    for (Staat staat : staatDAO.findByAllOrderedByNameStaat()) {
      if (!StringUtils.isBlank(staat.getIso3166Alpha2())) {
        result.put(staat.getIso3166Alpha2(), staat);
      }
    }

    return result;
  }

  @Override
  protected void aktualisiere(StaatenGruppe staatenGruppeInDatei, StaatenGruppe staatenGruppeInDB, StaatenGruppeImportContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    aktualisiereStaatenGruppe(staatenGruppeInDatei, staatenGruppeInDB);
  }

  private void aktualisiereStaatenGruppe(StaatenGruppe staatenGruppeInDatei, StaatenGruppe staatenGruppeInDB) {
    Map<String, Staat> persistenteStaatenNachIsoCode = mappeStaatenNachIso3166Alpha2();

    List<Staat> persistenteStaaten = new ArrayList<>();
    for (Staat staat : staatenGruppeInDatei.getStaats()) {
      if (!StringUtils.isBlank(staat.getIso3166Alpha2()) && persistenteStaatenNachIsoCode.containsKey(staat.getIso3166Alpha2())) {
        persistenteStaaten.add(persistenteStaatenNachIsoCode.get(staat.getIso3166Alpha2()));
      }
    }
    staatenGruppeInDB.removeAllStaats();
    for (Staat staat : persistenteStaaten) {
      staatenGruppeInDB.addStaat(staat);
    }

  }

  @Override
  protected void loescheAusDatenbank(Collection<StaatenGruppe> entitiesInDb, StaatenGruppeImportContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    for (StaatenGruppe staatenGruppe : entitiesInDb) {
      staatenGruppeDAO.remove(staatenGruppe);
    }
  }

  @Override
  protected List<StaatenGruppe> getAllEntitiesInDB(StaatenGruppeImportContext context) {
    if (context.getWahl() == null) {
      return staatenGruppeDAO.findByWahltermin(context.getWahltermin());
    }
    return staatenGruppeDAO.findByWahl(context.getWahl());
  }

  @Override
  protected Function<StaatenGruppe, StaatenGruppeUK> getEntityToEntityTKFunction() {
    return StaatenGruppeUK.getStaatenGruppeToUKFunction();
  }

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